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

/*
 *  Copyright (C) 2003-2004 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-downloader-sidebar.c 2863 2007-03-14 06:43:16Z ikezoe $
 */

#include "kz-downloader-sidebar.h"

#include <glib/gi18n.h>
#include "kazehakase.h"

enum {
	PROP_0,
	PROP_SIDEBAR
};


enum {
	TERMINATOR = -1,
	COLUMN_URI,
	COLUMN_LOCAL_FILE,
	COLUMN_PROGRESS,
	COLUMN_DOWNLOADER,
	N_COLUMNS
};


/* Object class methods */
static void     dispose      (GObject      *obj);
static void     set_property (GObject      *object,
                              guint         prop_id,
                              const GValue *value,
                              GParamSpec   *pspec);
static void     get_property (GObject      *object,
                              guint         prop_id,
                              GValue       *value,
                              GParamSpec   *pspec);

static GtkWidget *kz_downloader_sidebar_new_with_entry (KzSidebarEntry *entry,
							KzSidebar   *sidebar);


static KzSidebarEntry kz_sidebar_downloader = 
{
	/* .priority_hint = */ 0,
	/* .label         = */ N_("Downloader"),
	/* .icon          = */ NULL,
	/* .create        = */ kz_downloader_sidebar_new_with_entry,
};


KzSidebarEntry *
kz_downloader_sidebar_get_entry (gint idx)
{
	if (idx == 0)
		return &kz_sidebar_downloader;
	else
		return NULL;
}

G_DEFINE_TYPE(KzDownloaderSidebar, kz_downloader_sidebar, GTK_TYPE_VBOX)

static void
kz_downloader_sidebar_class_init (KzDownloaderSidebarClass *klass)
{
	GObjectClass *gobject_class;

	gobject_class = (GObjectClass *) klass;

	gobject_class->dispose      = dispose;
	gobject_class->set_property = set_property;
	gobject_class->get_property = get_property;

	g_object_class_install_property
		(gobject_class,
		 PROP_SIDEBAR,
		 g_param_spec_object ("sidebar",
				      _("Sidebar"),
				      _("The parent sidebar"),
				      KZ_TYPE_SIDEBAR,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));
}


static void
update_downloader_list (KzDownloaderSidebar *sidebar)
{
	GtkTreeView *view = GTK_TREE_VIEW(sidebar->tree_view);
	GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
	KzDownloaderGroup *group = sidebar->downloader_group;
	GSList *node;

	gtk_list_store_clear(store);
	for (node = group->items; node; node = g_slist_next(node))
	{
		KzDownloader *downloader = node->data;
		GtkTreeIter iter;

		if (!KZ_IS_DOWNLOADER(downloader)) continue;

		gtk_list_store_append(store, &iter);
		gtk_list_store_set(store, &iter,
				   COLUMN_URI,        downloader->uri,
				   COLUMN_LOCAL_FILE, downloader->filename,
				   COLUMN_PROGRESS,   0.0,
				   COLUMN_DOWNLOADER, downloader,
				   TERMINATOR);
	}
}


static void
cb_downloader_added (KzDownloaderGroup *group,
		     KzDownloader *downloader,
		     KzDownloaderSidebar *sidebar)
{
	GtkTreeView *view;
	GtkListStore *store;
	GtkTreeIter iter;

	g_return_if_fail(KZ_IS_DOWNLOADER_SIDEBAR(sidebar));
	g_return_if_fail(KZ_IS_DOWNLOADER(downloader));

	view = GTK_TREE_VIEW(sidebar->tree_view);
	store = GTK_LIST_STORE(gtk_tree_view_get_model(view));

	gtk_list_store_append(store, &iter);
	gtk_list_store_set(store, &iter,
			   COLUMN_URI,        downloader->uri,
			   COLUMN_LOCAL_FILE, downloader->filename,
			   COLUMN_DOWNLOADER, downloader,
			   TERMINATOR);
}


static gboolean
remove_row_func (GtkTreeModel *model,
		 GtkTreePath *path, GtkTreeIter *iter,
		 gpointer data)
{
	KzDownloader *downloader = NULL;

	gtk_tree_model_get(model, iter,
			   COLUMN_DOWNLOADER, &downloader,
			   TERMINATOR);

	if (downloader == KZ_DOWNLOADER(data))
	{
		gtk_list_store_remove(GTK_LIST_STORE(model), iter);
		g_object_unref(downloader);
		return TRUE;
	}
	if (downloader)
		g_object_unref(downloader);
		
	return FALSE;
}


static void
cb_downloader_removed (KzDownloaderGroup *group,
		       KzDownloader *downloader,
		       KzDownloaderSidebar *sidebar)
{
	GtkTreeView *view;
	GtkTreeModel *model;

	g_return_if_fail(KZ_IS_DOWNLOADER_SIDEBAR(sidebar));

	view = GTK_TREE_VIEW(sidebar->tree_view);
	model = gtk_tree_view_get_model(view);

	gtk_tree_model_foreach(model, remove_row_func, downloader);
}


static gboolean
set_progress_func (GtkTreeModel *model,
		   GtkTreePath *path, GtkTreeIter *iter,
		   gpointer data)
{
	KzDownloader *downloader = NULL;

	gtk_tree_model_get(model, iter,
			   COLUMN_DOWNLOADER, &downloader,
			   TERMINATOR);

	if (downloader == KZ_DOWNLOADER(data))
	{
		gdouble progress;

		progress = kz_downloader_get_percent(downloader) / 100.0;
		gtk_list_store_set(GTK_LIST_STORE(model), iter,
				   COLUMN_PROGRESS, progress,
				   TERMINATOR);
		g_object_unref(downloader);
		return TRUE;
	}
	if (downloader)
		g_object_unref(downloader);
		
	return FALSE;
}


static void
cb_downloader_progress (KzDownloaderGroup *group,
			KzDownloader *downloader,
			KzDownloaderSidebar *sidebar)
{
	GtkTreeView *view;
	GtkTreeModel *model;

	g_return_if_fail(KZ_IS_DOWNLOADER_SIDEBAR(sidebar));

	view = GTK_TREE_VIEW(sidebar->tree_view);
	model = gtk_tree_view_get_model(view);

	gtk_tree_model_foreach(model, set_progress_func, downloader);
}


static void
kz_downloader_sidebar_init (KzDownloaderSidebar *sidebar)
{
	GtkTreeView *tree_view;
	GtkWidget *scrwin, *widget;
	GtkListStore *store;
	KzDownloaderGroup *group;
	GtkCellRenderer *cell;
	GtkTreeViewColumn *column;

	/* create scrolled window and tree */
	scrwin = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin),
				       GTK_POLICY_AUTOMATIC,
				       GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwin),
					    GTK_SHADOW_IN);
	gtk_box_pack_start(GTK_BOX(sidebar), scrwin, TRUE, TRUE, 0);
	gtk_widget_show(scrwin);

	store = gtk_list_store_new(N_COLUMNS,
				   G_TYPE_STRING,
				   G_TYPE_STRING,
				   G_TYPE_DOUBLE,
				   KZ_TYPE_DOWNLOADER);
	widget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
	g_object_unref(store);
	sidebar->tree_view = widget;
	tree_view = GTK_TREE_VIEW(widget);
	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_view), TRUE);
	gtk_container_add(GTK_CONTAINER(scrwin), GTK_WIDGET(tree_view));
	gtk_widget_show(widget);

	cell = gtk_cell_renderer_progress_new();
	column = gtk_tree_view_column_new_with_attributes
			(_("Progress"), cell,
			 "percentage", COLUMN_PROGRESS,
			 NULL);
	gtk_tree_view_append_column(tree_view, column);

	cell = gtk_cell_renderer_text_new();
	column = gtk_tree_view_column_new_with_attributes
			(_("File"), cell,
			 "text",   COLUMN_LOCAL_FILE,
			 NULL);
	gtk_tree_view_append_column(tree_view, column);

	/* set data */
	group = kz_downloader_group_get_instance();
	sidebar->downloader_group = group;
	g_signal_connect(group, "add",
			 G_CALLBACK(cb_downloader_added), sidebar);
	g_signal_connect(group, "remove",
			 G_CALLBACK(cb_downloader_removed), sidebar);
	g_signal_connect(group, "progress",
			 G_CALLBACK(cb_downloader_progress), sidebar);

	update_downloader_list(sidebar);
}


static void
dispose (GObject *obj)
{
	KzDownloaderSidebar *sidebar = KZ_DOWNLOADER_SIDEBAR(obj);

	if (sidebar->sidebar)
		g_object_unref(sidebar->sidebar);
	sidebar->sidebar = NULL;

	if (sidebar->downloader_group)
	{
		g_signal_handlers_disconnect_by_func
			(sidebar->downloader_group,
			 G_CALLBACK(cb_downloader_added), sidebar);
		g_signal_handlers_disconnect_by_func
			(sidebar->downloader_group,
			 G_CALLBACK(cb_downloader_removed), sidebar);
		g_signal_handlers_disconnect_by_func
			(sidebar->downloader_group,
			 G_CALLBACK(cb_downloader_progress), sidebar);
		g_object_unref(sidebar->downloader_group);
	}
	sidebar->downloader_group = NULL;

	if (G_OBJECT_CLASS (kz_downloader_sidebar_parent_class)->dispose)
		G_OBJECT_CLASS (kz_downloader_sidebar_parent_class)->dispose(obj);
}


static void
set_property (GObject         *object,
              guint            prop_id,
              const GValue    *value,
              GParamSpec      *pspec)
{
	KzDownloaderSidebar *sidebar = KZ_DOWNLOADER_SIDEBAR(object);
  
	switch (prop_id)
	{
	case PROP_SIDEBAR:
		sidebar->sidebar = g_object_ref(g_value_get_object(value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static void
get_property (GObject         *object,
              guint            prop_id,
              GValue          *value,
              GParamSpec      *pspec)
{
	KzDownloaderSidebar *sidebar = KZ_DOWNLOADER_SIDEBAR(object);

	switch (prop_id)
	{
	case PROP_SIDEBAR:
		g_value_set_object(value, sidebar->sidebar);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


GtkWidget *
kz_downloader_sidebar_new (KzSidebar *sidebar)
{
	KzDownloaderSidebar *dsidebar;

	dsidebar = g_object_new(KZ_TYPE_DOWNLOADER_SIDEBAR,
				"sidebar", sidebar,
				NULL);

	return GTK_WIDGET(dsidebar);
}

static GtkWidget *
kz_downloader_sidebar_new_with_entry (KzSidebarEntry *entry, KzSidebar *sidebar)
{
	return kz_downloader_sidebar_new (sidebar);
}
