Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-bookmark-file.c

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

/*
 *  Copyright (C) 2003 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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.
 *
 *  $Id: kz-bookmark-file.c,v 1.16 2005/04/07 12:29:22 ikezoe Exp $
 */

#include "kz-bookmark-file.h"

#include <string.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "gobject-utils.h"
#include "glib-utils.h"
#include "utils.h"
#include "eggregex.h"

#include "kz-io.h"
#include "kz-xmlrpc.h"

/* bookmark_file file types */
#include "kz-xbel.h"
#include "kz-rss.h"
#include "kz-nsbookmark.h"
#include "kz-lirs.h"
#include "kz-hinadi.h"
#include "kz-w3mbookmark.h"

enum {
      LOAD_START_SIGNAL,
      LOAD_COMPLETED_SIGNAL,
      SAVE_START_SIGNAL,
      SAVE_COMPLETED_SIGNAL,
      ERROR_SIGNAL,
      LAST_SIGNAL
};

enum {
      PROP_0,
      PROP_BOOKMARK_FILE_LOCATION,
      PROP_FILE_TYPE,
      PROP_INTERVAL,
      PROP_XMLRPC,
      PROP_XMLRPC_USER,
      PROP_XMLRPC_PASS,
      PROP_EDITABLE,
      PROP_PREVIOUS_LAST_MODIFIED
};


#define ADD_BOOKMARK_FILE_TYPE(func)                        \
{                                                     \
      KzBookmarkFileType *type;                             \
      gint i;                                               \
      for (i = 0; (type = func(i)); i++)                    \
            file_types = g_list_append(file_types, type);         \
}

static void kz_bookmark_file_class_init   (KzBookmarkFileClass *klass);
static void kz_bookmark_file_init         (KzBookmarkFile      *bookmark_file);
static void kz_bookmark_file_dispose      (GObject             *object);
static void kz_bookmark_file_set_property (GObject             *object,
                                   guint                prop_id,
                                   const GValue        *value,
                                   GParamSpec          *pspec);
static void kz_bookmark_file_get_property (GObject             *object,
                                   guint                prop_id,
                                   GValue              *value,
                                   GParamSpec          *pspec);

static void kz_bookmark_file_set_state    (KzBookmarkFile      *bookmark_file,
                                 KzBookmarkFileState  state);
static void kz_bookmark_file_set_editable (KzBookmarkFile      *bookmark_file,
                                 gboolean             editable);

static gboolean kz_bookmark_file_is_loading_all_children (KzBookmark *bookmark);

static void     cb_io_load_complete       (KzIO *io,
                                 GError *error,
                                 KzBookmarkFile *bookmark_file);
static gboolean idle_load_complete        (gpointer data);

static KzBookmarkFileType *
            kz_bookmark_file_detect_file_type  (KzBookmarkFile *bookmark_file,
                                      gchar          *buf);

static KzBookmarkClass *parent_class = NULL;
static gint kz_bookmark_file_signals[LAST_SIGNAL] = {0};

static GList *file_types = NULL;

static GQuark location_quark          = 0;
static GQuark file_type_quark         = 0;
static GQuark interval_quark          = 0;
static GQuark xmlrpc_quark            = 0;
static GQuark xmlrpc_user_quark       = 0;
static GQuark xmlrpc_pass_quark       = 0;
static GQuark timer_quark             = 0;
static GQuark state_quark             = 0;
static GQuark io_quark                = 0;
static GQuark io_signal_id_quark      = 0;
static GQuark p_last_modified_quark   = 0;

KZ_OBJECT_GET_TYPE(kz_bookmark_file, "KzBookmarkFile", KzBookmarkFile,
               kz_bookmark_file_class_init, kz_bookmark_file_init,
               KZ_TYPE_BOOKMARK)


static void
kz_bookmark_file_class_init (KzBookmarkFileClass *klass)
{
      GObjectClass *object_class;

      if (!file_types)
      {
            ADD_BOOKMARK_FILE_TYPE(kz_rss_get_file_types);
            ADD_BOOKMARK_FILE_TYPE(kz_lirs_get_file_types);
            ADD_BOOKMARK_FILE_TYPE(kz_hinadi_get_file_types);
            ADD_BOOKMARK_FILE_TYPE(kz_xbel_get_file_types);
            ADD_BOOKMARK_FILE_TYPE(kz_nsbookmark_get_file_types);
            ADD_BOOKMARK_FILE_TYPE(kz_w3mbookmark_get_file_types);
      }

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

      object_class->dispose      = kz_bookmark_file_dispose;
      object_class->set_property = kz_bookmark_file_set_property;
      object_class->get_property = kz_bookmark_file_get_property;

      klass->load_start         = NULL;
      klass->load_completed     = NULL;
      klass->save_start         = NULL;
      klass->save_completed     = NULL;

      g_object_class_install_property(
            object_class,
             PROP_BOOKMARK_FILE_LOCATION,
             g_param_spec_string(
                   "location",
                   _("Location of bookmark_file file itself"),
                   _("The location of the bookmark_file file itself"),
                   NULL,
                   G_PARAM_READWRITE));

      g_object_class_install_property(
            object_class,
             PROP_FILE_TYPE,
             g_param_spec_string(
                   "file-type",
                   _("File type"),
                   _("File type of the bookmark_file file"),
                   NULL,
                   G_PARAM_READWRITE));

      g_object_class_install_property(
            object_class,
             PROP_INTERVAL,
             g_param_spec_uint(
                   "interval",
                   _("Interval"),
                   _("Update interval"),
                   0,
                   G_MAXUINT,
                   0,
                   G_PARAM_READWRITE));

      g_object_class_install_property(
            object_class,
             PROP_EDITABLE,
             g_param_spec_boolean(
                   "editable",
                   _("Editable"),
                   _("Whether attributes of the bookmark_file is writable or not"),
                   TRUE,
                   G_PARAM_READWRITE));
      
      g_object_class_install_property(
            object_class,
             PROP_XMLRPC,
             g_param_spec_string(
                   "xmlrpc",
                   _("XMLRPC"),
                   _("The interface address of the XML-RPC for shared bookmark_file"),
                   NULL,
                   G_PARAM_READWRITE));
      g_object_class_install_property(
            object_class,
             PROP_XMLRPC_USER,
             g_param_spec_string(
                   "xmlrpc-user",
                   _("XMLRPC User"),
                   _("The user name for XMLRPC"),
                   NULL,
                   G_PARAM_READWRITE));
      g_object_class_install_property(
            object_class,
             PROP_XMLRPC_PASS,
             g_param_spec_string(
                   "xmlrpc-pass",
                   _("XMLRPC Password"),
                   _("The password for XMLRPC"),
                   NULL,
                   G_PARAM_READWRITE));
      
      g_object_class_install_property(
            object_class,
             PROP_PREVIOUS_LAST_MODIFIED,
             g_param_spec_uint(
                   "previous-last-modified",
                   _("Previous Last Modified"),
                   _("The time of previous last modified"),
                   0,
                   G_MAXUINT,
                   0,
                   G_PARAM_READWRITE));

      kz_bookmark_file_signals[LOAD_START_SIGNAL]
            = g_signal_new("load_start",
                         G_TYPE_FROM_CLASS (klass),
                         G_SIGNAL_RUN_LAST,
                         G_STRUCT_OFFSET (KzBookmarkFileClass,
                                    load_start),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);

      kz_bookmark_file_signals[LOAD_COMPLETED_SIGNAL]
            = g_signal_new("load_completed",
                         G_TYPE_FROM_CLASS (klass),
                         G_SIGNAL_RUN_LAST,
                         G_STRUCT_OFFSET (KzBookmarkFileClass,
                                    load_completed),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);

      kz_bookmark_file_signals[SAVE_START_SIGNAL]
            = g_signal_new("save_start",
                         G_TYPE_FROM_CLASS (klass),
                         G_SIGNAL_RUN_LAST,
                         G_STRUCT_OFFSET (KzBookmarkFileClass,
                                    save_start),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);

      kz_bookmark_file_signals[SAVE_COMPLETED_SIGNAL]
            = g_signal_new("save_completed",
                         G_TYPE_FROM_CLASS (klass),
                         G_SIGNAL_RUN_LAST,
                         G_STRUCT_OFFSET (KzBookmarkFileClass,
                                    save_completed),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);

      kz_bookmark_file_signals[ERROR_SIGNAL]
            = g_signal_new("error",
                         G_TYPE_FROM_CLASS(klass),
                         G_SIGNAL_RUN_LAST,
                         G_STRUCT_OFFSET (KzBookmarkFileClass,
                                    error),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__STRING,
                         G_TYPE_NONE, 1, G_TYPE_STRING);

      location_quark        = g_quark_from_string("KzBookmarkFile::BookmarkFileLocation");
      file_type_quark       = g_quark_from_string("KzBookmarkFile::FileType");
      interval_quark        = g_quark_from_string("KzBookmarkFile::Interval");
      timer_quark           = g_quark_from_string("KzBookmarkFile::Timer");
      state_quark           = g_quark_from_string("KzBookmarkFile::State");
      io_quark              = g_quark_from_string("KzBookmarkFile::KzIO");
      io_signal_id_quark    = g_quark_from_string("KzBookmarkFile::KzIOSignalID");
      xmlrpc_quark          = g_quark_from_string("KzBookmarkFile::XMLRPC");
      xmlrpc_user_quark     = g_quark_from_string("KzBookmarkFile::XMLRPCUser");
      xmlrpc_pass_quark     = g_quark_from_string("KzBookmarkFile::XMLRPCPassword");
      p_last_modified_quark = g_quark_from_string("KzBookmarkFile::PreviousLastModified");
}


static void
kz_bookmark_file_init (KzBookmarkFile *bookmark_file)
{
}


static void
kz_bookmark_file_dispose (GObject *object)
{
      guint timer_id, io_id;
      KzIO *io;
      
      timer_id = GPOINTER_TO_UINT(g_object_get_qdata(object, timer_quark));
      if (timer_id)
            g_source_remove(timer_id);
      timer_id = 0;
      g_object_set_qdata(object, timer_quark, GUINT_TO_POINTER(timer_id));

      /* dispose KzIO object if exists */
      /* FIXME! we need more robust way */
      io = g_object_get_qdata(object, io_quark);
      if (io)
      {
            kz_io_stop(io);

      }

      io_id = GPOINTER_TO_UINT(g_object_get_qdata(object, io_signal_id_quark));
      if (io_id)
      {
            /* wait until disconnecting (i.e. loading stops  )*/
            while (g_signal_handler_is_connected(io, io_id))
                  gtk_main_iteration();
      }
      g_object_set_qdata(object, io_quark, NULL);

      io_id = 0;
      g_object_set_qdata(object, io_signal_id_quark,
                     GUINT_TO_POINTER(io_id));

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


#define CHANGE_STR(obj, quark, value) \
{ \
      g_object_set_qdata_full((obj), (quark), (value), \
                        (GDestroyNotify) g_free); \
}

static void
kz_bookmark_file_set_property (GObject *object,
                         guint prop_id,
                         const GValue *value,
                         GParamSpec *pspec)
{
      KzBookmarkFile *bookmark_file = KZ_BOOKMARK_FILE(object);

      switch (prop_id) {
      case PROP_BOOKMARK_FILE_LOCATION:
      {
            CHANGE_STR(object, location_quark,
                     g_value_dup_string(value));
            break;
      }
      case PROP_FILE_TYPE:
      {
            gchar *str = g_value_dup_string(value);
            KzBookmarkFileType *type;

            g_return_if_fail(!kz_bookmark_file_get_file_type(bookmark_file));

            CHANGE_STR(object, file_type_quark, str);

            if (str && *str)
            {
                  type = kz_bookmark_file_detect_file_type(bookmark_file, NULL);
                  if (type && type->init)
                        type->init(bookmark_file);
                  if (type && !type->to_string)
                  {
                        kz_bookmark_file_set_editable(bookmark_file, FALSE);
                        /*
                         * FIXME!!
                         * Also set all children as non-editable.
                         */
                  }
            }
            break;
      }
      case PROP_INTERVAL:
      {
            guint interval, timer_id;

            interval = g_value_get_uint(value);
            timer_id = GPOINTER_TO_UINT
                        (g_object_get_qdata(object, timer_quark));

            if (timer_id)
                  g_source_remove(timer_id);
            timer_id = 0;

            if (interval > 0)
                  timer_id = g_timeout_add(60000 * interval,
                                     (gpointer) kz_bookmark_file_load_start,
                                     bookmark_file);

            g_object_set_qdata(object, interval_quark,
                           GUINT_TO_POINTER(interval));
            g_object_set_qdata(object, timer_quark,
                           GUINT_TO_POINTER(timer_id));
            break;
      }
      case PROP_EDITABLE:
            if (g_value_get_boolean(value))
                  bookmark_file->flags |= KZ_BOOKMARK_FILE_EDITABLE_FLAG;
            else
                  bookmark_file->flags &= ~KZ_BOOKMARK_FILE_EDITABLE_FLAG;
            break;
      case PROP_XMLRPC:
            CHANGE_STR(object, xmlrpc_quark, g_value_dup_string(value));
            break;
      case PROP_XMLRPC_USER:
            CHANGE_STR(object, xmlrpc_user_quark, g_value_dup_string(value));
            break;
      case PROP_XMLRPC_PASS:
            CHANGE_STR(object, xmlrpc_pass_quark, g_value_dup_string(value));
            break;
      case PROP_PREVIOUS_LAST_MODIFIED:
      {
            guint t;

            t = g_value_get_uint(value);
            g_object_set_qdata(object, p_last_modified_quark,
                           GUINT_TO_POINTER(t));
            break;
      }
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}


static void
kz_bookmark_file_get_property (GObject *object,
                           guint prop_id,
                           GValue *value,
                           GParamSpec *pspec)
{
      KzBookmarkFile *bookmark_file = KZ_BOOKMARK_FILE(object);
      gchar *str;

      switch (prop_id) {
      case PROP_BOOKMARK_FILE_LOCATION:
            str = g_object_get_qdata(object, location_quark);
            g_value_set_string(value, str);
            break;
      case PROP_FILE_TYPE:
            str = g_object_get_qdata(object, file_type_quark);
            g_value_set_string(value, str);
            break;
      case PROP_INTERVAL:
      {
            guint interval;

            interval = GPOINTER_TO_UINT
                        (g_object_get_qdata(object, interval_quark));
            g_value_set_uint(value, interval);
            break;
      }
      case PROP_EDITABLE:
            if (bookmark_file->flags & KZ_BOOKMARK_FILE_EDITABLE_FLAG)
                  g_value_set_boolean(value, TRUE);
            else
                  g_value_set_boolean(value, FALSE);
            break;
      case PROP_XMLRPC:
            str = g_object_get_qdata(object, xmlrpc_quark);
            g_value_set_string(value, str);
            break;
      case PROP_XMLRPC_USER:
            str = g_object_get_qdata(object, xmlrpc_user_quark);
            g_value_set_string(value, str);
            break;
      case PROP_XMLRPC_PASS:
            str = g_object_get_qdata(object, xmlrpc_pass_quark);
            g_value_set_string(value, str);
            break;
      case PROP_PREVIOUS_LAST_MODIFIED:
      {
            guint t;

            t = GPOINTER_TO_UINT(g_object_get_qdata(object, p_last_modified_quark));
            g_value_set_uint(value, t);
            break;
      }
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}


KzBookmarkFile *
kz_bookmark_file_new (const gchar *location,
                  const gchar *title,
                  const gchar *file_type)
{
      KzBookmarkFile *bookmark_file;

      location = location ? location : "";

      bookmark_file = g_object_new(KZ_TYPE_BOOKMARK_FILE,
                             "type",                   KZ_BOOKMARK_FOLDER,
                             "location",               location,
                             "title",                  title,
                             "file-type",              file_type,
                             "previous-last-modified", 0,
                             NULL);

      return bookmark_file;
}


KzBookmarkFile *
kz_bookmark_file_create_new (const gchar *location,
                       const gchar *title,
                       const gchar *file_type)
{
      KzBookmarkFile *bookmark_file;
      KzBookmarkFileType *type;

      if (!location)
      {
            g_warning(_("kz_bookmark_file_file_create_new(): "
                      "location is not specified!"));
            location = "";
      }

      bookmark_file = g_object_new(KZ_TYPE_BOOKMARK_FILE,
                             "type",      KZ_BOOKMARK_FOLDER,
                             "location",  location,
                             "title",     title,
                             "file-type", file_type,
                             NULL);

      type = kz_bookmark_file_detect_file_type(bookmark_file, NULL);
      if (type && type->from_string)
      {
            if (!kz_bookmark_file_get_file_type(bookmark_file))
                  kz_bookmark_file_set_file_type(bookmark_file, type->file_type);
            type->from_string(bookmark_file, NULL, 0, NULL);
      }

      return bookmark_file;
}


const gchar *
kz_bookmark_file_get_location (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), NULL);
      return g_object_get_qdata(G_OBJECT(bookmark_file), location_quark);
}


guint
kz_bookmark_file_get_interval (KzBookmarkFile *bookmark)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark), 0);
      return GPOINTER_TO_UINT(g_object_get_qdata(G_OBJECT(bookmark),
                                       interval_quark));
}


const gchar *
kz_bookmark_file_get_xmlrpc (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), NULL);
      return g_object_get_qdata(G_OBJECT(bookmark_file), xmlrpc_quark);
}


const gchar *
kz_bookmark_file_get_xmlrpc_user (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), NULL);
      return g_object_get_qdata(G_OBJECT(bookmark_file), xmlrpc_user_quark);
}


const gchar *
kz_bookmark_file_get_xmlrpc_pass (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), NULL);
      return g_object_get_qdata(G_OBJECT(bookmark_file), xmlrpc_pass_quark);
}


const gchar *
kz_bookmark_file_get_file_type (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), NULL);
      return g_object_get_qdata(G_OBJECT(bookmark_file), file_type_quark);
}


gboolean
kz_bookmark_file_is_editable (KzBookmarkFile *bookmark_file)
{
      KzBookmarkFileType *type;

      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), FALSE);
      
      if (!kz_bookmark_file_get_file_type(bookmark_file))
            return FALSE;

      if (g_str_has_prefix(kz_bookmark_file_get_location(bookmark_file), "http://") &&
          !kz_bookmark_file_get_xmlrpc(bookmark_file))
            return FALSE;

      type = kz_bookmark_file_detect_file_type(bookmark_file, NULL);
      if (type && type->to_string)
            return TRUE;

      return TRUE;
}


void
kz_bookmark_file_set_location (KzBookmarkFile *bookmark_file,
                         const gchar *location)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "location", location, NULL);
}


void
kz_bookmark_file_set_file_type (KzBookmarkFile *bookmark_file,
                          const gchar *file_type)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "file-type", file_type, NULL);
}


void
kz_bookmark_file_set_interval (KzBookmarkFile *bookmark_file, guint interval)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "interval", interval, NULL);
}

void
kz_bookmark_file_set_xmlrpc (KzBookmarkFile *bookmark_file,
                         const gchar *xmlrpc)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "xmlrpc", xmlrpc, NULL);
}

void
kz_bookmark_file_set_xmlrpc_user (KzBookmarkFile *bookmark_file,
                              const gchar *user)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "xmlrpc-user", user, NULL);
}

void
kz_bookmark_file_set_xmlrpc_pass (KzBookmarkFile *bookmark_file,
                              const gchar *pass)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "xmlrpc-pass", pass, NULL);
}


static void
kz_bookmark_file_set_editable (KzBookmarkFile *bookmark_file, gboolean editable)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));
      g_object_set(G_OBJECT(bookmark_file), "editable", editable, NULL);
}


/*****************************************************************************
 *                                                                           *
 *                        load/save booomark file                            *
 *                                                                           *
 *****************************************************************************/
gboolean
kz_bookmark_file_load_start (KzBookmarkFile *bookmark_file)
{
      KzIO *io;
      const gchar *uri;
      guint id, last_mod;
      KzBookmarkFileState state;

      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), FALSE);

      uri = kz_bookmark_file_get_location(KZ_BOOKMARK_FILE(bookmark_file));
      if (!uri) return FALSE;

      /* preventing to insert children bookmark_file twice, but silly! */
      state = kz_bookmark_file_get_state(bookmark_file);
      if (state == KZ_BOOKMARK_FILE_STATE_LOADING)
            return TRUE;
      
      /* check loading state */
      if (kz_bookmark_file_is_loading_all_children(KZ_BOOKMARK(bookmark_file)))
            return TRUE;
      kz_bookmark_file_set_state(bookmark_file, KZ_BOOKMARK_FILE_STATE_LOADING);

      last_mod = kz_bookmark_get_last_modified(KZ_BOOKMARK(bookmark_file));
      g_object_set(bookmark_file, "previous-last-modified", last_mod, NULL);

      g_signal_emit(bookmark_file,
                  kz_bookmark_file_signals[LOAD_START_SIGNAL],
                  0);

      kz_bookmark_remove_all(KZ_BOOKMARK(bookmark_file));

      io = kz_io_new(uri);
      id = g_signal_connect(io, "io_completed",
                        G_CALLBACK(cb_io_load_complete),
                        bookmark_file);

      g_object_set_qdata(G_OBJECT(bookmark_file), io_quark, io);
      g_object_set_qdata(G_OBJECT(bookmark_file), io_signal_id_quark,
                     GUINT_TO_POINTER(id));

      kz_io_load_to_buffer(io);

      return TRUE;
}


void
kz_bookmark_file_load_stop (KzBookmarkFile *bookmark_file)
{
      g_warning("kz_bookmark_file_load_stop() is not implemented yet.");
}


gboolean
kz_bookmark_file_save_start (KzBookmarkFile *bookmark_file)
{
      g_warning("kz_bookmark_file_save_start() is not implemented yet.");
      return FALSE;
}


void
kz_bookmark_file_save_stop (KzBookmarkFile *bookmark_file)
{
      g_warning("kz_bookmark_file_save_stop() is not implemented yet.");
}

#warning! FIXME! this is available only for local bookmark_file.
void
kz_bookmark_file_load (KzBookmarkFile *bookmark_file)
{
      const gchar *file;
      gchar *str = NULL;
      gsize length;

      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));

      file = kz_bookmark_file_get_location(bookmark_file);

      if (file && *file)
      {
            if (g_file_get_contents(file, &str, &length, NULL))
            {
                  KzBookmarkFileType *type;
                  type = kz_bookmark_file_detect_file_type(bookmark_file, str);
                  if (!type)
                        /* use default? */;
                  if (type && type->from_string)
                  {
                        if (!kz_bookmark_file_get_file_type(bookmark_file))
                              kz_bookmark_file_set_file_type(bookmark_file, type->file_type);
                        type->from_string(bookmark_file, str, length, NULL);
                  }
                  g_free(str);
            }
      }
}


void
kz_bookmark_file_save (KzBookmarkFile *bookmark_file)
{
      KzBookmarkFileType *type;
      KzIO *io;
      const gchar *file;
      gchar *str;

      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));

      type = kz_bookmark_file_detect_file_type(bookmark_file, NULL);
      if (!type || !type->to_string) return;

      file = kz_bookmark_file_get_location(bookmark_file);
      str = type->to_string(bookmark_file);

      if (file && *file && str && *str)
      {
            io = kz_io_new(file);
            kz_io_write(io, str);
            g_object_unref(io);
            g_free(str);
      }
}


static gboolean
idle_load_complete (gpointer data)
{
      KzIO *io = data;

      g_object_unref(G_OBJECT(io));

      return FALSE;
}


static void
cb_io_load_complete (KzIO *io, GError *error, KzBookmarkFile *bookmark_file)
{     
      KzBookmarkFileType *type;
      const gchar *buf;
      guint size;

      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));

      if (error) goto ERROR;

      buf  = kz_io_get_buffer(io);
      size = kz_io_get_loaded_size(io);

      if (!buf || size == 0) goto ERROR;

      type = kz_bookmark_file_detect_file_type(bookmark_file, (gchar *)buf);
      if (!type)
            /* use default? */;
      if (type && type->from_string)
      {
            if (!kz_bookmark_file_get_file_type(bookmark_file))
                  kz_bookmark_file_set_file_type(bookmark_file, type->file_type);
            type->from_string(bookmark_file, buf, size, NULL);
      }

ERROR:
      g_signal_handlers_disconnect_by_func
            (io,
             G_CALLBACK(cb_io_load_complete),
             bookmark_file);
      kz_bookmark_file_set_state(bookmark_file, KZ_BOOKMARK_FILE_STATE_NORMAL);
      g_object_set_qdata(G_OBJECT(bookmark_file), io_quark, NULL);
      g_object_set_qdata(G_OBJECT(bookmark_file), io_signal_id_quark,
                     GPOINTER_TO_UINT(0));

      if (error)
      {
            g_signal_emit(bookmark_file,
                        kz_bookmark_file_signals[ERROR_SIGNAL],
                        0,
                        "Load failed");
      }
      else 
      {
            g_signal_emit(bookmark_file,
                        kz_bookmark_file_signals[LOAD_COMPLETED_SIGNAL],
                        0);
      }
      g_idle_add(idle_load_complete, io);
}


static KzBookmarkFileType *
kz_bookmark_file_detect_file_type (KzBookmarkFile *bookmark_file, gchar *buf)
{
      GList *node;
      const gchar *type_str;

      type_str = kz_bookmark_file_get_file_type(bookmark_file);
      g_return_val_if_fail(type_str || buf, NULL);

      for (node = file_types; node; node = g_list_next(node))
      {
            KzBookmarkFileType *type = node->data;
 
            if (type_str)
            {
                  /* Fixed, or already detected */

                  if (type->file_type &&
                      !strcmp(type_str, type->file_type))
                  {
                        return type;
                  }
            }
            else
            {
                  /* Auto detect */

                  if (type && type->is_supported &&
                      type->is_supported(bookmark_file, buf))
                  {
                        return type;
                  }
            }
      }

      return NULL;
}


static void
kz_bookmark_file_set_state (KzBookmarkFile *bookmark_file, KzBookmarkFileState state)
{
      g_return_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file));

      if (state == KZ_BOOKMARK_FILE_STATE_LOADING)
            g_object_set_qdata(G_OBJECT(bookmark_file), state_quark,
                           GINT_TO_POINTER(state));
      else
            g_object_set_qdata(G_OBJECT(bookmark_file), state_quark,
                           GINT_TO_POINTER(KZ_BOOKMARK_FILE_STATE_NORMAL));
}


KzBookmarkFileState
kz_bookmark_file_get_state (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file),
                       KZ_BOOKMARK_FILE_STATE_NORMAL);

      return GPOINTER_TO_INT(g_object_get_qdata(G_OBJECT(bookmark_file),
                                      state_quark));
}

static gboolean
kz_bookmark_file_is_loading_all_children (KzBookmark *bookmark)
{
      gboolean ret = FALSE;
      GList *children, *node, *next;
      g_return_val_if_fail(KZ_IS_BOOKMARK(bookmark), FALSE);
      
      /* check loading state */
      children = kz_bookmark_get_children(bookmark);

      node = children;
      while (node)
      {
            KzBookmark *child = node->data;
            if (kz_bookmark_has_children(child))
            {
                  ret = kz_bookmark_file_is_loading_all_children(child);
                  if (ret) break;
            }
            next = g_list_next(node);
            if (KZ_IS_BOOKMARK_FILE(child))
            {
                  KzBookmarkFileState state;
                  state = kz_bookmark_file_get_state(KZ_BOOKMARK_FILE(child));
                  ret = (state == KZ_BOOKMARK_FILE_STATE_LOADING) ? TRUE : FALSE;
                  if (ret) break;
            }
            node = next;
      }
      g_list_free(children);

      return ret;
}


gboolean
kz_bookmark_file_has_xmlrpc (KzBookmarkFile *bookmark_file)
{
      return (kz_bookmark_file_get_xmlrpc(bookmark_file) != NULL);
}


static void
cb_xml_rpc_completed(KzXMLRPC *xmlrpc, GError *error, gpointer data)
{
      const GList *results;
      KzBookmark *file;

      g_signal_handlers_disconnect_by_func(xmlrpc,
                                   G_CALLBACK(cb_xml_rpc_completed),
                                   data);
      results = kz_xml_rpc_get_results(xmlrpc);
      if (results)
      {
            const gchar *id;
            id = (const gchar*)g_list_nth_data((GList*)results, 0);
            if (data && KZ_IS_BOOKMARK(data))
            {
                  kz_bookmark_set_id(KZ_BOOKMARK(data), id);
                  file = kz_bookmark_get_parent_file (KZ_BOOKMARK(data));
                  /* fake signal */
                  g_signal_emit(file,
                              kz_bookmark_file_signals[LOAD_COMPLETED_SIGNAL],
                              0);
                  kz_bookmark_file_set_state(KZ_BOOKMARK_FILE(file),
                                       KZ_BOOKMARK_FILE_STATE_NORMAL);
            }
      }
      g_object_unref(xmlrpc);
}


void
kz_bookmark_file_xmlrpc_insert (KzBookmarkFile *file, 
                        KzBookmark *folder,
                        KzBookmark *sibling,
                        KzBookmark *child)
{
      KzXMLRPC *xmlrpc;
      const gchar *xmlrpc_uri;
      const gchar *title, *link, *desc;
      const gchar *folder_id = NULL, *sibling_id = NULL;
      const gchar *type;

      xmlrpc_uri = kz_bookmark_file_get_xmlrpc(file);
      if (!xmlrpc_uri) return;

      folder_id = kz_bookmark_get_id(folder);
      if (!folder_id) folder_id = "0";
      if (sibling)
            sibling_id = kz_bookmark_get_id(sibling);
      if (!sibling_id) sibling_id = "0";

      if (kz_bookmark_is_separator(child))
            type = "separator";
      else if (kz_bookmark_is_folder(child))
            type = "folder";
      else 
            type = "bookmark";

      title = kz_bookmark_get_title(child);
      link  = kz_bookmark_get_link(child);
      desc  = kz_bookmark_get_description(child);

      xmlrpc = kz_xml_rpc_new(xmlrpc_uri);
      g_signal_connect(xmlrpc, "xml_rpc_completed", 
                   G_CALLBACK(cb_xml_rpc_completed), child);
      kz_xml_rpc_call(xmlrpc, "bookmark.insert",
                  kz_bookmark_file_get_location(file), 
                  "user", "pass",
                  folder_id, sibling_id,
                  type,
                  "title", title, 
                  "link", link, 
                  "desc", desc,
                  NULL);
      /* fake signal */
      kz_bookmark_file_set_state(file, KZ_BOOKMARK_FILE_STATE_LOADING);
      g_signal_emit(file,
                  kz_bookmark_file_signals[LOAD_START_SIGNAL],
                  0);
}


void
kz_bookmark_file_xmlrpc_remove (KzBookmarkFile *file,
                        KzBookmark *child)
{
      KzXMLRPC *xmlrpc;
      const gchar *xmlrpc_uri;
      const gchar *id = NULL;

      xmlrpc_uri = kz_bookmark_file_get_xmlrpc(file);
      if (!xmlrpc_uri) return;

      id = kz_bookmark_get_id(child);

      xmlrpc = kz_xml_rpc_new(xmlrpc_uri);
      g_signal_connect(xmlrpc, "xml_rpc_completed", 
                   G_CALLBACK(cb_xml_rpc_completed), NULL);
      kz_xml_rpc_call(xmlrpc, "bookmark.remove",
                  kz_bookmark_file_get_location(file), 
                  "user", "pass",
                  id,
                  NULL);
}


void
kz_bookmark_file_xmlrpc_move (KzBookmarkFile *file, 
                        KzBookmark *folder,
                        KzBookmark *sibling,
                        KzBookmark *child)
{
      KzXMLRPC *xmlrpc;
      const gchar *xmlrpc_uri;
      const gchar *id = NULL, *folder_id = NULL, *sibling_id = NULL;

      xmlrpc_uri = kz_bookmark_file_get_xmlrpc(file);
      if (!xmlrpc_uri) return;

      id = kz_bookmark_get_id(child);
      if (!id) return;

      folder_id = kz_bookmark_get_id(folder);
      if (!folder_id) folder_id = "0";
      if (sibling)
            sibling_id = kz_bookmark_get_id(sibling);
      if (!sibling_id) sibling_id = "0";

      xmlrpc = kz_xml_rpc_new(xmlrpc_uri);
      g_signal_connect(xmlrpc, "xml_rpc_completed", 
                   G_CALLBACK(cb_xml_rpc_completed), NULL);
      kz_xml_rpc_call(xmlrpc, "bookmark.move",
                  kz_bookmark_file_get_location(file), 
                  "user", "pass",
                  id,
                  folder_id, sibling_id,
                  NULL);
}

      
guint
kz_bookmark_file_get_previous_last_modified (KzBookmarkFile *bookmark_file)
{
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), 0);

      return GPOINTER_TO_UINT(g_object_get_qdata(G_OBJECT(bookmark_file),
                                       p_last_modified_quark));
}

gboolean
kz_bookmark_file_is_update (KzBookmarkFile *bookmark_file)
{
      guint last_time, time;
      
      g_return_val_if_fail(KZ_IS_BOOKMARK_FILE(bookmark_file), FALSE);

      last_time = kz_bookmark_file_get_previous_last_modified(bookmark_file);
      time = kz_bookmark_get_last_modified(KZ_BOOKMARK(bookmark_file));

      return last_time < time ? TRUE : FALSE;
}


Generated by  Doxygen 1.6.0   Back to index