Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-favicon.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *
 *  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.
 */

#include "gobject-utils.h"
#include "kz-favicon.h"
#include "kz-profile.h"
#include "kz-downloader.h"
#include "utils.h"
#include "glib-utils.h"

typedef struct _KzFaviconPrivate    KzFaviconPrivate;
struct _KzFaviconPrivate
{
      GHashTable *uri_hash;
      KzProfile  *uri_list;

      guint n_favicon;
};
#define KZ_FAVICON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), KZ_TYPE_FAVICON, KzFaviconPrivate))

enum {
      READY_SIGNAL,
      LAST_SIGNAL
};

#define MAX_FAVICONS 2000

static void kz_favicon_class_init   (KzFaviconClass *klass);
static void kz_favicon_init         (KzFavicon *kzfav);
static void kz_favicon_dispose      (GObject *object);

static void kz_favicon_load_uri_list        (KzFavicon *kzfav);
static void kz_favicon_uri_hash_to_uri_list (gpointer key,
                                   gpointer value,
                                   KzFavicon *kzfav);

static void cb_downloader_load_complete (KzDownloader *dl,
                               const gchar *uri);
static void cb_downloader_load_error    (KzDownloader *dl,
                               const gchar *uri);

static GObjectClass *parent_class     = NULL;
static KzFavicon    *kzfavicon_single = NULL;

static gint kz_favicon_signals[LAST_SIGNAL] = {0};

KZ_OBJECT_GET_TYPE(kz_favicon, "KzFavicon", KzFavicon,
               kz_favicon_class_init, kz_favicon_init,
               G_TYPE_OBJECT)

static void
kz_favicon_class_init (KzFaviconClass *klass)
{
      GObjectClass *object_class;

      parent_class = g_type_class_peek_parent (klass);
      object_class = (GObjectClass *) klass;

      object_class->dispose  = kz_favicon_dispose;
      
      klass->ready = NULL;

      kz_favicon_signals[READY_SIGNAL]
            = g_signal_new ("ready",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzFaviconClass, ready),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__STRING,
                        G_TYPE_NONE, 1,
                        G_TYPE_STRING);
      g_type_class_add_private (object_class, sizeof(KzFaviconPrivate));
}


static void
kz_favicon_init (KzFavicon *kzfav)
{
      gchar *favicon_file;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);

      favicon_file = g_build_filename(g_get_home_dir(),
                                "."PACKAGE,
                              "faviconrc",
                              NULL);
      priv->uri_list = kz_profile_open(favicon_file, NULL);
      g_free(favicon_file);
      kz_profile_set_save_each_time(priv->uri_list, FALSE);

      priv->uri_hash = g_hash_table_new_full (g_str_hash,
                                    g_str_equal,
                                    (GDestroyNotify)g_free,
                                    (GDestroyNotify)g_free);
      kz_favicon_load_uri_list(kzfav);
      kz_profile_close(priv->uri_list);
}


static void
kz_favicon_dispose (GObject *object)
{
      KzFavicon *kzfav = KZ_FAVICON(object);
      gchar *favicon_file;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);
      
      favicon_file = g_build_filename(g_get_home_dir(),
                              "."PACKAGE,
                              "faviconrc",
                              NULL);

      priv->uri_list = kz_profile_open(favicon_file, NULL);
      g_free(favicon_file);
      kz_profile_set_save_each_time(priv->uri_list, FALSE);

      kz_profile_delete_section(priv->uri_list, "URI");
      priv->n_favicon = 0;
      
      /* convert hash table to KzProfileList */
      g_hash_table_foreach(priv->uri_hash,
                       (GHFunc)kz_favicon_uri_hash_to_uri_list,
                       kzfav);

      kz_profile_close(priv->uri_list);
      g_hash_table_destroy(priv->uri_hash);

      priv->uri_list = NULL;
      priv->uri_hash = NULL;

      if (G_OBJECT_CLASS (parent_class)->dispose)
            G_OBJECT_CLASS (parent_class)->dispose(object);
}


KzFavicon *
kz_favicon_new (void)
{
      KzFavicon *kzfav = g_object_new(KZ_TYPE_FAVICON, NULL);

      return kzfav;
}


KzFavicon *
kz_favicon_get_instance (void)
{
      if (!kzfavicon_single)
            kzfavicon_single = kz_favicon_new();
      else
            g_object_ref(kzfavicon_single);

      return kzfavicon_single;
}


static void
kz_favicon_load_uri_list (KzFavicon *kzfav)
{
      KzProfileList *p;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);
      KzProfile *uri_list = priv->uri_list;
      
      for (p = uri_list->list; p; p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY 
                && g_strcmp(p->section, "URI") == 0)
            {
                  g_hash_table_insert(priv->uri_hash,
                                  g_strdup(p->key),
                                  g_strdup(p->value));
            }
      }
}


static void
kz_favicon_uri_hash_to_uri_list (gpointer key, gpointer value, KzFavicon *kzfav)
{
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);
      if (priv->n_favicon > MAX_FAVICONS)
            return;

      kz_profile_set_value(priv->uri_list, "URI",
                       (const gchar*)key, (const gchar *)value,
                       strlen((gchar *)value) + 1,
                       KZ_PROFILE_VALUE_TYPE_STRING);

      priv->n_favicon++;
}


static gboolean
idle_unref_dl(gpointer data)
{
      KzDownloader *dl = data;

      g_object_unref(G_OBJECT(dl));

      return FALSE;
}


static void
kz_downloader_disconnect_signal(KzDownloader *dl, const gchar *uri)
{
      g_signal_handlers_disconnect_by_func(dl,
                                   G_CALLBACK(cb_downloader_load_complete),
                                   (gpointer)uri);
      g_signal_handlers_disconnect_by_func(dl,
                                   G_CALLBACK(cb_downloader_load_error),
                                   (gpointer)uri);
}

static void
cb_downloader_load_complete (KzDownloader *dl, const gchar *uri)
{     
      GQuark quark;

      quark = g_quark_from_string(uri);

      kz_downloader_disconnect_signal(dl, uri);
      g_idle_add(idle_unref_dl, dl);

      /* FIXME! Do not use kzfavicon_sigle object! */
      g_signal_emit(kzfavicon_single,
                  kz_favicon_signals[READY_SIGNAL],
                  quark,
                  uri); 
}


static void
cb_downloader_load_error (KzDownloader *dl, const gchar *uri)
{
      gchar *hash_key;
      KzFavicon *kzfav = kzfavicon_single;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);

      kz_downloader_disconnect_signal(dl, uri);
      g_idle_add(idle_unref_dl, dl);

      hash_key = create_profile_key_from_uri(uri);
      g_hash_table_remove(priv->uri_hash, hash_key);
      g_free(hash_key); 
}


GtkWidget *
kz_favicon_get_widget (KzFavicon *kzfav, const gchar *uri, GtkIconSize size)
{
      GtkWidget *icon = NULL;
      const gchar *favicon_file_name;
      gchar *hash_key;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);

      if (uri == NULL)
            return NULL;

      hash_key = create_profile_key_from_uri(uri);
      favicon_file_name = g_hash_table_lookup(priv->uri_hash, hash_key);
      g_free(hash_key);

      if (!favicon_file_name)
            return NULL;

      if (g_file_test(favicon_file_name, G_FILE_TEST_EXISTS))
      {
            GdkPixbuf *scaled_pixbuf, *orig_pixbuf;
            gint width, height;

            gtk_icon_size_lookup(size, &width, &height);

            orig_pixbuf = gdk_pixbuf_new_from_file(favicon_file_name, NULL);
            if (!orig_pixbuf) return NULL;

            scaled_pixbuf = gdk_pixbuf_scale_simple(orig_pixbuf,
                                          width, height,
                                          GDK_INTERP_BILINEAR);
            icon = gtk_image_new_from_pixbuf(scaled_pixbuf); 

            g_object_unref(orig_pixbuf);
            g_object_unref(scaled_pixbuf);
      }

      return icon;
}

GdkPixbuf *
kz_favicon_get_pixbuf (KzFavicon *kzfav, const gchar *uri, GtkIconSize size)
{
      GdkPixbuf *icon = NULL;
      const gchar *favicon_file_name;
      gchar *hash_key;
      KzFaviconPrivate *priv = KZ_FAVICON_GET_PRIVATE (kzfav);

      if (uri == NULL)
            return NULL;

      hash_key = create_profile_key_from_uri(uri);
      favicon_file_name = g_hash_table_lookup(priv->uri_hash, hash_key);
      g_free(hash_key);

      if (!favicon_file_name)
            return NULL;

      if (g_file_test(favicon_file_name, G_FILE_TEST_EXISTS))
      {
            GdkPixbuf *orig_pixbuf;
            gint width, height;
            
            gtk_icon_size_lookup(size, &width, &height);

            orig_pixbuf = gdk_pixbuf_new_from_file(favicon_file_name, NULL);
            if (!orig_pixbuf) return NULL;

            icon = gdk_pixbuf_scale_simple(orig_pixbuf,
                                     width, height,
                                     GDK_INTERP_BILINEAR);

            g_object_unref(orig_pixbuf);
      }

      return icon;
}

void
kz_favicon_get_icon_from_uri (KzFavicon *kzfav, 
                        const gchar *uri,
                        const gchar *document_uri)
{
      gchar *favicon_filename;
      gchar *favicon_file_location;
      gchar *hash_key;
      const gchar *old_value;
      KzDownloader *dl;
      KzFaviconPrivate *priv;

      g_return_if_fail(KZ_IS_FAVICON(kzfav));
      priv = KZ_FAVICON_GET_PRIVATE (kzfav);

      if (!uri) return;
      hash_key = create_profile_key_from_uri(document_uri);

      favicon_filename = create_filename_from_uri(uri);
      favicon_file_location = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "favicon",
                                     favicon_filename,
                                     NULL);
      g_free(favicon_filename);
      
      old_value = g_hash_table_lookup(priv->uri_hash,
                              hash_key);
      
      if (old_value && !strcmp(old_value, favicon_file_location))
      {
            GQuark quark;
            quark = g_quark_from_string(document_uri);
            
            g_signal_emit(kzfav,
                        kz_favicon_signals[READY_SIGNAL],
                        quark,
                        document_uri);
            g_free(hash_key);
            g_free(favicon_file_location);
            return;
      }

      g_hash_table_insert(priv->uri_hash,
                      g_strdup(hash_key),
                      g_strdup(favicon_file_location));

      /* start download */
      dl = kz_downloader_new_with_filename(uri, favicon_file_location);
      if (dl)
      {
            g_signal_connect(dl, "completed",
                         G_CALLBACK(cb_downloader_load_complete),
                         (gpointer)document_uri);
            g_signal_connect(dl, "error",
                         G_CALLBACK(cb_downloader_load_error),
                         (gpointer)document_uri);
            kz_downloader_to_file(dl);
      }

      g_free(hash_key);
      g_free(favicon_file_location);
}


Generated by  Doxygen 1.6.0   Back to index