From: Enrico Tröger Date: Sat, 6 Jun 2009 21:40:08 +0000 (+0200) Subject: Use only one GtkTreeStore for all browsers to improve performance X-Git-Url: https://spindle.queued.net/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=246fc03151e29a8dac78eb824eaa7ef673772b0d;p=midori Use only one GtkTreeStore for all browsers to improve performance Split the code a bit more and use one GtkTreeStore for all CookieManagerPage instances so we save some cycles when updating the store when cookies have changed. --- diff --git a/extensions/cookie-manager/cookie-manager-page.c b/extensions/cookie-manager/cookie-manager-page.c index 9e73fe38..71df49df 100644 --- a/extensions/cookie-manager/cookie-manager-page.c +++ b/extensions/cookie-manager/cookie-manager-page.c @@ -28,22 +28,17 @@ typedef struct _CookieManagerPagePrivate CookieManagerPagePrivate; #define CM_EMPTY_LABEL_TEXT "\n\n\n\n\n\n" -enum -{ - COOKIE_MANAGER_COL_NAME, - COOKIE_MANAGER_COL_COOKIE, - COOKIE_MANAGER_COL_VISIBLE, - COOKIE_MANAGER_N_COLUMNS -}; - struct _CookieManagerPagePrivate { + CookieManager *parent; + GtkWidget *treeview; GtkTreeStore *store; GtkTreeModel *filter; GtkWidget *filter_entry; + gboolean ignore_changed_filter; GtkWidget *desc_label; GtkWidget *delete_button; @@ -53,11 +48,13 @@ struct _CookieManagerPagePrivate GtkWidget *toolbar; GtkWidget *popup_menu; +}; - GSList *cookies; - SoupCookieJar *jar; - guint timer_id; - gint ignore_changed_count; +enum +{ + PROP_0, + PROP_STORE, + PROP_PARENT }; @@ -69,7 +66,6 @@ static void cm_button_delete_all_clicked_cb(GtkToolButton *button, CookieManager static void cm_tree_popup_collapse_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp); static void cm_tree_popup_expand_activate_cb(GtkMenuItem *item, CookieManagerPage *cmp); static void cm_filter_tree(CookieManagerPage *cmp, const gchar *filter_text); -static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, CookieManagerPage *cmp); G_DEFINE_TYPE_WITH_CODE(CookieManagerPage, cookie_manager_page, GTK_TYPE_VBOX, @@ -90,22 +86,6 @@ static const gchar *cookie_manager_page_get_stock_id(MidoriViewable *viewable) } -static void cm_free_cookie_list(CookieManagerPage *cmp) -{ - CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); - - if (priv->cookies != NULL) - { - GSList *l; - - for (l = priv->cookies; l != NULL; l = g_slist_next(l)) - soup_cookie_free(l->data); - g_slist_free(priv->cookies); - priv->cookies = NULL; - } -} - - static void cm_create_toolbar(CookieManagerPage *cmp) { CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); @@ -174,74 +154,20 @@ static void cookie_manager_page_viewable_iface_init(MidoriViewableIface* iface) } -static void cookie_manager_page_finalize(GObject *object) +static void cookie_manager_page_pre_cookies_change_cb(CookieManager *cm, CookieManagerPage *cmp) { - CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object); - - g_signal_handlers_disconnect_by_func(priv->jar, cm_jar_changed_cb, object); - - if (priv->timer_id > 0) - g_source_remove(priv->timer_id); - - cm_free_cookie_list(COOKIE_MANAGER_PAGE(object)); - - gtk_widget_destroy(priv->popup_menu); + CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); - G_OBJECT_CLASS(cookie_manager_page_parent_class)->finalize(object); + g_object_ref(priv->filter); + gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), NULL); } -static void cm_refresh_store(CookieManagerPage *cmp) +static void cookie_manager_page_cookies_changed_cb(CookieManager *cm, CookieManagerPage *cmp) { - GSList *l; - GHashTable *parents; - GtkTreeIter iter; - GtkTreeIter *parent_iter; - SoupCookie *cookie; const gchar *filter_text; CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); - g_object_ref(priv->filter); - gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), NULL); - - gtk_tree_store_clear(priv->store); - - /* free the old list */ - cm_free_cookie_list(cmp); - - priv->cookies = soup_cookie_jar_all_cookies(priv->jar); - - /* Hashtable holds domain names as keys, the corresponding tree iters as values */ - parents = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - - for (l = priv->cookies; l != NULL; l = g_slist_next(l)) - { - cookie = l->data; - - /* look for the parent item for the current domain name and create it if it doesn't exist */ - if ((parent_iter = (GtkTreeIter*) g_hash_table_lookup(parents, cookie->domain)) == NULL) - { - parent_iter = g_new0(GtkTreeIter, 1); - - gtk_tree_store_append(priv->store, parent_iter, NULL); - gtk_tree_store_set(priv->store, parent_iter, - COOKIE_MANAGER_COL_NAME, cookie->domain, - COOKIE_MANAGER_COL_COOKIE, NULL, - COOKIE_MANAGER_COL_VISIBLE, TRUE, - -1); - - g_hash_table_insert(parents, g_strdup(cookie->domain), parent_iter); - } - - gtk_tree_store_append(priv->store, &iter, parent_iter); - gtk_tree_store_set(priv->store, &iter, - COOKIE_MANAGER_COL_NAME, cookie->name, - COOKIE_MANAGER_COL_COOKIE, cookie, - COOKIE_MANAGER_COL_VISIBLE, TRUE, - -1); - } - g_hash_table_destroy(parents); - gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter)); g_object_unref(priv->filter); @@ -255,32 +181,78 @@ static void cm_refresh_store(CookieManagerPage *cmp) } -static gboolean cm_delayed_refresh(CookieManagerPage *cmp) +static void cookie_manager_page_filter_changed_cb(CookieManager *cm, const gchar *text, + CookieManagerPage *cmp) { CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); - cm_refresh_store(cmp); - priv->timer_id = 0; - - return FALSE; + priv->ignore_changed_filter = TRUE; + gtk_entry_set_text(GTK_ENTRY(priv->filter_entry), text); + priv->ignore_changed_filter = FALSE; } -static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, - CookieManagerPage *cmp) +static void cookie_manager_page_finalize(GObject *object) { - CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); + CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object); + + gtk_widget_destroy(priv->popup_menu); + + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_pre_cookies_change_cb, object); + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_cookies_changed_cb, object); + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_filter_changed_cb, object); - if (priv->ignore_changed_count > 0) + G_OBJECT_CLASS(cookie_manager_page_parent_class)->finalize(object); +} + + +static void cookie_manager_page_set_property(GObject *object, guint prop_id, const GValue *value, + GParamSpec *pspec) +{ + CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(object); + switch (prop_id) { - priv->ignore_changed_count--; - return; - } + case PROP_STORE: + { + priv->store = g_value_get_object(value); - /* We delay these events a little bit to avoid too many rebuilds of the tree. - * Some websites (like Flyspray bugtrackers sent a whole bunch of cookies at once. */ - if (priv->timer_id == 0) - priv->timer_id = g_timeout_add_seconds(1, (GSourceFunc) cm_delayed_refresh, cmp); + /* setting filter and model */ + priv->filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store), NULL); + gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(priv->filter), + COOKIE_MANAGER_COL_VISIBLE); + gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter)); + g_object_unref(priv->filter); + + break; + } + case PROP_PARENT: + { + if (priv->parent != NULL) + { + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_pre_cookies_change_cb, object); + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_cookies_changed_cb, object); + g_signal_handlers_disconnect_by_func(priv->parent, + cookie_manager_page_filter_changed_cb, object); + } + priv->parent = g_value_get_object(value); + + g_signal_connect(priv->parent, "pre-cookies-change", + G_CALLBACK(cookie_manager_page_pre_cookies_change_cb), object); + g_signal_connect(priv->parent, "cookies-changed", + G_CALLBACK(cookie_manager_page_cookies_changed_cb), object); + g_signal_connect(priv->parent, "filter-changed", + G_CALLBACK(cookie_manager_page_filter_changed_cb), object); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } @@ -288,7 +260,27 @@ static void cookie_manager_page_class_init(CookieManagerPageClass *klass) { GObjectClass *g_object_class; g_object_class = G_OBJECT_CLASS(klass); + g_object_class->finalize = cookie_manager_page_finalize; + g_object_class->set_property = cookie_manager_page_set_property; + + g_object_class_install_property(g_object_class, + PROP_STORE, + g_param_spec_object( + "store", + "Treestore", + "The tree store", + GTK_TYPE_TREE_STORE, + G_PARAM_WRITABLE)); + + g_object_class_install_property(g_object_class, + PROP_PARENT, + g_param_spec_object( + "parent", + "Parent", + "The CookieManager parent instance", + COOKIE_MANAGER_TYPE, + G_PARAM_WRITABLE)); g_type_class_add_private(klass, sizeof(CookieManagerPagePrivate)); } @@ -346,13 +338,7 @@ static void cm_delete_cookie(CookieManagerPage *cmp, GtkTreeModel *model, GtkTre gtk_tree_model_get(model, child, COOKIE_MANAGER_COL_COOKIE, &cookie, -1); - if (cookie != NULL) - { - priv->ignore_changed_count++; - - soup_cookie_jar_delete_cookie(priv->jar, cookie); - /* the SoupCookie object is freed when the whole list gets updated */ - } + cookie_manager_delete_cookie(priv->parent, cookie); } @@ -670,11 +656,17 @@ static void cm_filter_tree(CookieManagerPage *cmp, const gchar *filter_text) static void cm_filter_entry_changed_cb(GtkEditable *editable, CookieManagerPage *cmp) { - const gchar *text = gtk_entry_get_text(GTK_ENTRY(editable)); + const gchar *text; CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(cmp); + if (priv->ignore_changed_filter) + return; + + text = gtk_entry_get_text(GTK_ENTRY(editable)); cm_filter_tree(cmp, text); + cookie_manager_update_filter(priv->parent, text); + if (*text != '\0') gtk_tree_view_expand_all(GTK_TREE_VIEW(priv->treeview)); else @@ -830,20 +822,6 @@ static GtkWidget *cm_tree_prepare(CookieManagerPage *cmp) sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); - /* create the main store */ - priv->store = gtk_tree_store_new(COOKIE_MANAGER_N_COLUMNS, - G_TYPE_STRING, SOUP_TYPE_COOKIE, G_TYPE_BOOLEAN); - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(priv->store), - COOKIE_MANAGER_COL_NAME, GTK_SORT_ASCENDING); - - /* setting filter and model */ - priv->filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store), NULL); - gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(priv->filter), - COOKIE_MANAGER_COL_VISIBLE); - gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview), GTK_TREE_MODEL(priv->filter)); - g_object_unref(priv->store); - g_object_unref(priv->filter); - /* signals */ g_signal_connect(sel, "changed", G_CALLBACK(cm_tree_selection_changed_cb), cmp); g_signal_connect(treeview, "button-press-event", G_CALLBACK(cm_tree_button_press_event_cb), cmp); @@ -909,9 +887,12 @@ static void cookie_manager_page_init(CookieManagerPage *self) GtkWidget *filter_hbox; GtkWidget *filter_label; GtkWidget *treeview; - SoupSession *session; CookieManagerPagePrivate *priv = COOKIE_MANAGER_PAGE_GET_PRIVATE(self); + priv->parent = NULL; + priv->store = NULL; + priv->ignore_changed_filter = FALSE; + cm_create_toolbar(self); priv->desc_label = gtk_label_new(CM_EMPTY_LABEL_TEXT); @@ -968,18 +949,19 @@ static void cookie_manager_page_init(CookieManagerPage *self) gtk_box_pack_start(GTK_BOX(self), filter_hbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(self), paned, TRUE, TRUE, 0); - - /* setup soup */ - session = webkit_get_default_session(); - priv->jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, soup_cookie_jar_get_type())); - g_signal_connect(priv->jar, "changed", G_CALLBACK(cm_jar_changed_cb), self); - - cm_refresh_store(self); } -GtkWidget *cookie_manager_page_new(void) +GtkWidget *cookie_manager_page_new(CookieManager *parent, GtkTreeStore *store, + const gchar *filter_text) { - return g_object_new(COOKIE_MANAGER_PAGE_TYPE, NULL); + GtkWidget *cmp; + + cmp = g_object_new(COOKIE_MANAGER_PAGE_TYPE, "parent", parent, "store", store, NULL); + + if (filter_text != NULL) + cookie_manager_page_filter_changed_cb(parent, filter_text, COOKIE_MANAGER_PAGE(cmp)); + + return cmp; } diff --git a/extensions/cookie-manager/cookie-manager-page.h b/extensions/cookie-manager/cookie-manager-page.h index 37e02c0d..7c307d1e 100644 --- a/extensions/cookie-manager/cookie-manager-page.h +++ b/extensions/cookie-manager/cookie-manager-page.h @@ -38,7 +38,9 @@ struct _CookieManagerPageClass }; GType cookie_manager_page_get_type (void); -GtkWidget* cookie_manager_page_new (void); +GtkWidget* cookie_manager_page_new (CookieManager *parent, + GtkTreeStore *store, + const gchar *filter_text); G_END_DECLS diff --git a/extensions/cookie-manager/cookie-manager.c b/extensions/cookie-manager/cookie-manager.c index 38d557a6..dc256722 100644 --- a/extensions/cookie-manager/cookie-manager.c +++ b/extensions/cookie-manager/cookie-manager.c @@ -16,115 +16,324 @@ #include "cookie-manager.h" #include "cookie-manager-page.h" +typedef struct _CookieManagerPrivate CookieManagerPrivate; +#define COOKIE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ + COOKIE_MANAGER_TYPE, CookieManagerPrivate)) -typedef struct +struct _CookieManager +{ + GObject parent; +}; + +struct _CookieManagerClass +{ + GObjectClass parent_class; +}; + +struct _CookieManagerPrivate { MidoriApp *app; - MidoriBrowser *browser; MidoriExtension *extension; - GtkWidget *panel_page; -} CMData; -static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext); -static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata); + GSList *panel_pages; + + GtkTreeStore *store; + GSList *cookies; + SoupCookieJar *jar; + guint timer_id; + gint ignore_changed_count; + gchar *filter_text; +}; +static void cookie_manager_finalize(GObject *object); +static void cookie_manager_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, + CookieManager *cm); -static void cm_browser_close_cb(GtkObject *browser, CMData *cmdata) +enum { - g_signal_handlers_disconnect_by_func(cmdata->extension, cm_deactivate_cb, cmdata); - g_signal_handlers_disconnect_by_func(cmdata->browser, cm_browser_close_cb, cmdata); + COOKIES_CHANGED, + PRE_COOKIES_CHANGE, + FILTER_CHANGED, - /* the panel_page widget gets destroyed automatically when a browser is closed but not - * when the extension is deactivated */ - if (cmdata->panel_page != NULL && IS_COOKIE_MANAGER_PAGE(cmdata->panel_page)) - gtk_widget_destroy(cmdata->panel_page); + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL]; - g_free(cmdata); + +G_DEFINE_TYPE(CookieManager, cookie_manager, G_TYPE_OBJECT); + + +static void cookie_manager_class_init(CookieManagerClass *klass) +{ + GObjectClass *g_object_class; + + g_object_class = G_OBJECT_CLASS(klass); + + g_object_class->finalize = cookie_manager_finalize; + + signals[COOKIES_CHANGED] = g_signal_new( + "cookies-changed", + G_TYPE_FROM_CLASS(klass), + (GSignalFlags) 0, + 0, + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[PRE_COOKIES_CHANGE] = g_signal_new( + "pre-cookies-change", + G_TYPE_FROM_CLASS(klass), + (GSignalFlags) 0, + 0, + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[FILTER_CHANGED] = g_signal_new( + "filter-changed", + G_TYPE_FROM_CLASS(klass), + (GSignalFlags) 0, + 0, + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + g_type_class_add_private(klass, sizeof(CookieManagerPrivate)); } -static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata) +static void cookie_manager_panel_pages_foreach(gpointer ptr, gpointer data) { - g_signal_handlers_disconnect_by_func(cmdata->app, cm_app_add_browser_cb, extension); - cm_browser_close_cb(NULL, cmdata); + if (ptr != NULL && GTK_IS_WIDGET(ptr)) + gtk_widget_destroy(GTK_WIDGET(ptr)); } -static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext) +static void cookie_manager_page_destroy_cb(GtkObject *page, CookieManager *cm) { - GtkWidget *panel; + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + priv->panel_pages = g_slist_remove(priv->panel_pages, page); +} + + +static void cookie_manager_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, + CookieManager *cm) +{ + MidoriPanel *panel; GtkWidget *page; - CMData *cmdata; + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); panel = katze_object_get_object(browser, "panel"); - page = cookie_manager_page_new(); + page = cookie_manager_page_new(cm, priv->store, priv->filter_text); gtk_widget_show(page); - midori_panel_append_page(MIDORI_PANEL(panel), MIDORI_VIEWABLE(page)); - - cmdata = g_new0(CMData, 1); - cmdata->app = app; - cmdata->browser = browser; - cmdata->extension = ext; - cmdata->panel_page = page; + midori_panel_append_page(panel, MIDORI_VIEWABLE(page)); + g_signal_connect(page, "destroy", G_CALLBACK(cookie_manager_page_destroy_cb), cm); - g_signal_connect(browser, "destroy", G_CALLBACK(cm_browser_close_cb), cmdata); - g_signal_connect(ext, "deactivate", G_CALLBACK(cm_deactivate_cb), cmdata); + priv->panel_pages = g_slist_append(priv->panel_pages, page); g_object_unref(panel); } -static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data) +static void cookie_manager_free_cookie_list(CookieManager *cm) { + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + if (priv->cookies != NULL) + { + GSList *l; + + for (l = priv->cookies; l != NULL; l = g_slist_next(l)) + soup_cookie_free(l->data); + g_slist_free(priv->cookies); + priv->cookies = NULL; + } +} + + +static void cookie_manager_refresh_store(CookieManager *cm) +{ + GSList *l; + GHashTable *parents; + GtkTreeIter iter; + GtkTreeIter *parent_iter; + SoupCookie *cookie; + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + g_signal_emit(cm, signals[PRE_COOKIES_CHANGE], 0); + + gtk_tree_store_clear(priv->store); + + /* free the old list */ + cookie_manager_free_cookie_list(cm); + + priv->cookies = soup_cookie_jar_all_cookies(priv->jar); + + /* Hashtable holds domain names as keys, the corresponding tree iters as values */ + parents = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + for (l = priv->cookies; l != NULL; l = g_slist_next(l)) + { + cookie = l->data; + + /* look for the parent item for the current domain name and create it if it doesn't exist */ + if ((parent_iter = (GtkTreeIter*) g_hash_table_lookup(parents, cookie->domain)) == NULL) + { + parent_iter = g_new0(GtkTreeIter, 1); + + gtk_tree_store_append(priv->store, parent_iter, NULL); + gtk_tree_store_set(priv->store, parent_iter, + COOKIE_MANAGER_COL_NAME, cookie->domain, + COOKIE_MANAGER_COL_COOKIE, NULL, + COOKIE_MANAGER_COL_VISIBLE, TRUE, + -1); + + g_hash_table_insert(parents, g_strdup(cookie->domain), parent_iter); + } + + gtk_tree_store_append(priv->store, &iter, parent_iter); + gtk_tree_store_set(priv->store, &iter, + COOKIE_MANAGER_COL_NAME, cookie->name, + COOKIE_MANAGER_COL_COOKIE, cookie, + COOKIE_MANAGER_COL_VISIBLE, TRUE, + -1); + } + g_hash_table_destroy(parents); + + g_signal_emit(cm, signals[COOKIES_CHANGED], 0); +} + + +static gboolean cookie_manager_delayed_refresh(CookieManager *cm) +{ + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + cookie_manager_refresh_store(cm); + priv->timer_id = 0; + + return FALSE; +} + + +static void cookie_manager_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, + CookieManager *cm) +{ + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + if (priv->ignore_changed_count > 0) + { + priv->ignore_changed_count--; + return; + } + + /* We delay these events a little bit to avoid too many rebuilds of the tree. + * Some websites (like Flyspray bugtrackers sent a whole bunch of cookies at once. */ + if (priv->timer_id == 0) + priv->timer_id = g_timeout_add_seconds(1, (GSourceFunc) cookie_manager_delayed_refresh, cm); +} + + +static void cookie_manager_finalize(GObject *object) +{ + CookieManager *cm = COOKIE_MANAGER(object); + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + g_signal_handlers_disconnect_by_func(priv->app, cookie_manager_app_add_browser_cb, cm); + g_signal_handlers_disconnect_by_func(priv->jar, cookie_manager_jar_changed_cb, cm); + + /* remove all panel pages from open windows */ + g_slist_foreach(priv->panel_pages, cookie_manager_panel_pages_foreach, NULL); + g_slist_free(priv->panel_pages); + + /* clean cookies */ + if (priv->timer_id > 0) + g_source_remove(priv->timer_id); + + cookie_manager_free_cookie_list(cm); + + g_object_unref(priv->store); + g_free(priv->filter_text); + + G_OBJECT_CLASS(cookie_manager_parent_class)->finalize(object); +} + + +static void cookie_manager_init(CookieManager *self) +{ + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(self); + SoupSession *session; + + priv->filter_text = NULL; + priv->panel_pages = NULL; + /* create the main store */ + priv->store = gtk_tree_store_new(COOKIE_MANAGER_N_COLUMNS, + G_TYPE_STRING, SOUP_TYPE_COOKIE, G_TYPE_BOOLEAN); + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(priv->store), + COOKIE_MANAGER_COL_NAME, GTK_SORT_ASCENDING); + + /* setup soup */ + session = webkit_get_default_session(); + priv->jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, soup_cookie_jar_get_type())); + g_signal_connect(priv->jar, "changed", G_CALLBACK(cookie_manager_jar_changed_cb), self); + + cookie_manager_refresh_store(self); +} + + +void cookie_manager_update_filter(CookieManager *cm, const gchar *text) +{ + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + katze_assign(priv->filter_text, g_strdup(text)); + + g_signal_emit(cm, signals[FILTER_CHANGED], 0, text); +} + + +void cookie_manager_delete_cookie(CookieManager *cm, SoupCookie *cookie) +{ + CookieManagerPrivate *priv = COOKIE_MANAGER_GET_PRIVATE(cm); + + if (cookie != NULL) + { + priv->ignore_changed_count++; + + soup_cookie_jar_delete_cookie(priv->jar, cookie); + /* the SoupCookie object is freed when the whole list gets updated */ + } +} + + +CookieManager *cookie_manager_new(MidoriExtension *extension, MidoriApp *app) +{ + CookieManager *cm; + CookieManagerPrivate *priv; guint i; KatzeArray *browsers; MidoriBrowser *browser; + cm = g_object_new(COOKIE_MANAGER_TYPE, NULL); + + priv = COOKIE_MANAGER_GET_PRIVATE(cm); + priv->app = app; + priv->extension = extension; + /* add the cookie manager panel page to existing browsers */ browsers = katze_object_get_object(app, "browsers"); i = 0; while ((browser = katze_array_get_nth_item(browsers, i++))) - cm_app_add_browser_cb(app, browser, extension); + cookie_manager_app_add_browser_cb(app, browser, cm); g_object_unref(browsers); - g_signal_connect(app, "add-browser", G_CALLBACK(cm_app_add_browser_cb), extension); -} - + g_signal_connect(app, "add-browser", G_CALLBACK(cookie_manager_app_add_browser_cb), cm); -MidoriExtension *extension_init(void) -{ - MidoriExtension *extension; - GtkIconFactory *factory; - GtkIconSource *icon_source; - GtkIconSet *icon_set; - static GtkStockItem items[] = - { - { STOCK_COOKIE_MANAGER, N_("_Cookie Manager"), 0, 0, NULL } - }; - - factory = gtk_icon_factory_new(); - gtk_stock_add(items, G_N_ELEMENTS(items)); - icon_set = gtk_icon_set_new(); - icon_source = gtk_icon_source_new(); - gtk_icon_source_set_icon_name(icon_source, GTK_STOCK_DIALOG_AUTHENTICATION); - gtk_icon_set_add_source(icon_set, icon_source); - gtk_icon_source_free(icon_source); - gtk_icon_factory_add(factory, STOCK_COOKIE_MANAGER, icon_set); - gtk_icon_set_unref(icon_set); - gtk_icon_factory_add_default(factory); - g_object_unref(factory); - - extension = g_object_new(MIDORI_TYPE_EXTENSION, - "name", _("Cookie Manager"), - "description", _("List, view and delete cookies"), - "version", "0.2", - "authors", "Enrico Tröger ", - NULL); - - g_signal_connect(extension, "activate", G_CALLBACK(cm_activate_cb), NULL); - - return extension; + return cm; } + diff --git a/extensions/cookie-manager/cookie-manager.h b/extensions/cookie-manager/cookie-manager.h index 9f6a3996..4e2ba32b 100644 --- a/extensions/cookie-manager/cookie-manager.h +++ b/extensions/cookie-manager/cookie-manager.h @@ -13,8 +13,38 @@ #ifndef __COOKIE_MANAGER_H__ #define __COOKIE_MANAGER_H__ +G_BEGIN_DECLS #define STOCK_COOKIE_MANAGER "cookie-manager" +enum +{ + COOKIE_MANAGER_COL_NAME, + COOKIE_MANAGER_COL_COOKIE, + COOKIE_MANAGER_COL_VISIBLE, + COOKIE_MANAGER_N_COLUMNS +}; -#endif /* __COOKIE_MANAGER_H__ */ + +#define COOKIE_MANAGER_TYPE (cookie_manager_get_type()) +#define COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + COOKIE_MANAGER_TYPE, CookieManager)) +#define COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + COOKIE_MANAGER_TYPE, CookieManagerClass)) +#define IS_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + COOKIE_MANAGER_TYPE)) +#define IS_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + COOKIE_MANAGER_TYPE)) + +typedef struct _CookieManager CookieManager; +typedef struct _CookieManagerClass CookieManagerClass; + +GType cookie_manager_get_type (void); +CookieManager* cookie_manager_new (MidoriExtension *extension, MidoriApp *app); + +void cookie_manager_delete_cookie(CookieManager *cm, SoupCookie *cookie); +void cookie_manager_update_filter(CookieManager *cm, const gchar *text); + +G_END_DECLS + +#endif /* __COOKIE-MANAGER_H__ */ diff --git a/extensions/cookie-manager/main.c b/extensions/cookie-manager/main.c new file mode 100644 index 00000000..39d058e9 --- /dev/null +++ b/extensions/cookie-manager/main.c @@ -0,0 +1,66 @@ +/* + Copyright (C) 2009 Enrico Tröger + + 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 "config.h" +#include + +#include "cookie-manager.h" + +CookieManager *cm = NULL; + + +static void cm_deactivate_cb(MidoriExtension *extension, gpointer data) +{ + g_object_unref(cm); +} + + +static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data) +{ + cm = cookie_manager_new(extension, app); +} + + +MidoriExtension *extension_init(void) +{ + MidoriExtension *extension; + GtkIconFactory *factory; + GtkIconSource *icon_source; + GtkIconSet *icon_set; + static GtkStockItem items[] = + { + { STOCK_COOKIE_MANAGER, N_("_Cookie Manager"), 0, 0, NULL } + }; + + factory = gtk_icon_factory_new(); + gtk_stock_add(items, G_N_ELEMENTS(items)); + icon_set = gtk_icon_set_new(); + icon_source = gtk_icon_source_new(); + gtk_icon_source_set_icon_name(icon_source, GTK_STOCK_DIALOG_AUTHENTICATION); + gtk_icon_set_add_source(icon_set, icon_source); + gtk_icon_source_free(icon_source); + gtk_icon_factory_add(factory, STOCK_COOKIE_MANAGER, icon_set); + gtk_icon_set_unref(icon_set); + gtk_icon_factory_add_default(factory); + g_object_unref(factory); + + extension = g_object_new(MIDORI_TYPE_EXTENSION, + "name", _("Cookie Manager"), + "description", _("List, view and delete cookies"), + "version", "0.2", + "authors", "Enrico Tröger ", + NULL); + + g_signal_connect(extension, "activate", G_CALLBACK(cm_activate_cb), NULL); + g_signal_connect(extension, "deactivate", G_CALLBACK(cm_deactivate_cb), NULL); + + return extension; +} diff --git a/po/POTFILES.in b/po/POTFILES.in index 0ae02a7b..b461abc2 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -30,6 +30,7 @@ extensions/adblock.c extensions/colorful-tabs.c extensions/cookie-manager/cookie-manager.c extensions/cookie-manager/cookie-manager-page.c +extensions/cookie-manager/main.c extensions/feed-panel/feed-atom.c extensions/feed-panel/feed-panel.c extensions/feed-panel/feed-parse.c