/* giFTui * Copyright (C) 2003 the giFTui team * * 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 of the * License, 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 "main.h" #include #include #include #include "io.h" #include "event.h" #include "configure.h" #include "util.h" #include "ui.h" #include "ui_icon.h" #include "ui_util.h" #include "ui_transfer_cb.h" /* Currently not used... */ /*static void giftui_transferfile_fill (Interface *iface, InterfaceNode *inode, GiftuiTransferFile_t *file) { if (!inode->value) return; if (!strcasecmp (inode->key, "url")) { if (file->str_url) g_free (file->str_url); file->str_url = g_strdup (inode->key); return; } if (!strcasecmp (inode->key, "user")) { if (file->str_user) g_free (file->str_user); file->str_user = g_strdup (inode->value); return; } if (!strcasecmp (inode->key, "status")) { if (file->str_state) g_free (file->str_state); file->str_state = g_strdup (inode->value); return; } if (!strcasecmp (inode->key, "transmit")) { file->transmit = atol (inode->value); return; } if (!strcasecmp (inode->key, "elapsed")) { file->elapsed = atol (inode->value); return; } if (!strcasecmp (inode->key, "hash")) { if (file->str_hash) g_free (file->str_hash); file->str_hash = g_strdup (inode->value); } return; }*/ static void giftui_transferchunk_fill (Interface *iface, InterfaceNode *inode, GiftuiTransferChunk_t *file) { if (!inode->value) return; if (!strcasecmp (inode->key, "url")) { file->str_url = inode->value; return; } if (!strcasecmp (inode->key, "user")) { file->str_user = inode->value; return; } if (!strcasecmp (inode->key, "status")) { file->str_state = inode->value; return; } if (!strcasecmp (inode->key, "transmit")) { file->transmit = atol (inode->value); return; } if (!strcasecmp (inode->key, "start")) { file->start = atol (inode->value); return; } if (!strcasecmp (inode->key, "elapsed")) { file->elapsed = atol (inode->value); return; } return; } /**/ static GtkCellRendererProgressColor _state_from_str (const gchar *str) { if (!str) return GTK_CELL_RENDERER_PROGRESS_ACTIVE; if (!strcasecmp (str, "paused")) return GTK_CELL_RENDERER_PROGRESS_PAUSED; if (!strcasecmp (str, "active")) return GTK_CELL_RENDERER_PROGRESS_ACTIVE; if (!strcasecmp (str, "completed")) return GTK_CELL_RENDERER_PROGRESS_COMPLETED; return GTK_CELL_RENDERER_PROGRESS_CANCELED; } static gboolean _find_transfer_user (GtkTreeModel *model, GtkTreeIter *parent, GtkTreeIter *child, const gchar *user) { gboolean ret = FALSE; gchar *stored_user; if (!user) return ret; ret = gtk_tree_model_iter_children (model, child, parent); while (ret) { gtk_tree_model_get (model, child, TRANSFER_FILENAME, &stored_user, -1); if (stored_user) { if (!strcmp (user, stored_user)) { g_free (stored_user); return TRUE; } g_free (stored_user); } ret = gtk_tree_model_iter_next (model, child); } return ret; } static gboolean _find_transfer_id (GtkTreeModel *model, GtkTreeIter *iter, guint id) { gboolean ret; guint stored_id; ret = gtk_tree_model_get_iter_first (model, iter); while (ret) { gtk_tree_model_get (model, iter, TRANSFER_ID, &stored_id, -1); if (stored_id == id) return TRUE; ret = gtk_tree_model_iter_next (model, iter); } return FALSE; } static gboolean _find_transfer_file (GtkTreeModel *model, GtkTreeIter *iter, gulong filesize, const gchar *hash) { gboolean ret; gulong stored_size; if (!hash) return FALSE; ret = gtk_tree_model_get_iter_first (model, iter); while (ret) { gtk_tree_model_get (model, iter, TRANSFER_FILESIZE, &stored_size, -1); if (stored_size == filesize) { gchar *stored_hash; gtk_tree_model_get (model, iter, TRANSFER_HASH, &stored_hash, -1); if (stored_hash) { if (!strcmp (stored_hash, hash)) { g_free (stored_hash); return ret; } g_free (stored_hash); } } ret = gtk_tree_model_iter_next (model, iter); } return ret; } /**/ static void giftui_transfer_updownload_add_chunk (Interface *iface, InterfaceNode *inode, GiftuiTransferFile_t *file) { gchar *tmp, *icon; GiftuiIconType_t type; GiftuiTransferChunk_t chunk; if (!(inode == NULL || !strcasecmp (inode->key, "SOURCE"))) return; memset (&chunk, 0, sizeof (GiftuiTransferChunk_t)); if (inode) interface_foreach_ex (iface, inode, (InterfaceForeach) giftui_transferchunk_fill, &chunk); else interface_foreach (iface, NULL, (InterfaceForeach) giftui_transferchunk_fill, &chunk); chunk.str_size = size_str_human (chunk.transmit); if (!strcasecmp (iface->command, "ADDUPLOAD")) type = ICON_TRANSFER_UP; else type = ICON_TRANSFER_DOWN; chunk.str_speed = speed_str_human (0); if ((tmp = network_name_from_url (chunk.str_url))) { icon = giftui_icon_stock (type, tmp); g_free (tmp); } else icon = NULL; gtk_tree_store_append (GTK_TREE_STORE (file->model), &file->child, &file->parent); gtk_tree_store_set (GTK_TREE_STORE (file->model), &file->child, TRANSFER_SIZE, chunk.str_size, TRANSFER_TRANSMIT, chunk.transmit, TRANSFER_PROGRESS, size_percent (file->filesize, chunk.transmit), TRANSFER_START, size_percent (file->filesize, chunk.start), TRANSFER_STATE, chunk.str_state, TRANSFER_FILENAME, chunk.str_user, TRANSFER_SPEED, chunk.str_speed, TRANSFER_TRSPEED, chunk.speed, TRANSFER_URL, chunk.str_url, TRANSFER_ICON, icon, TRANSFER_COLOR, GTK_CELL_RENDERER_PROGRESS_ACTIVE, -1); if (chunk.str_size) g_free (chunk.str_size); if (chunk.str_speed) g_free (chunk.str_speed); if (icon) g_free (icon); return; } void giftui_transfer_updownload_add (GiftuiTransfer *tr, GiftuiEvent_t *in) { GiftuiTransferFile_t file; g_return_if_fail (tr != NULL); g_return_if_fail (in != NULL); memset ((void *) &file, 0, sizeof (GiftuiTransferFile_t)); /* Do we fill the up or down list ? */ if (in->type == EVENT_ADDDOWNLOAD || in->type == EVENT_ADDSOURCE) { file.model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->down_list)); file.treeview = tr->down_list; } else if (in->type == EVENT_ADDUPLOAD) { file.model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->up_list)); file.treeview = tr->up_list; } else return; /* Global stats need to be updated. */ tr->stats_updated = FALSE; file.filesize = INTERFACE_GETLU (in->iface, "size"); file.str_size = size_str_human (file.filesize); if (in->type == EVENT_ADDSOURCE) { if (_find_transfer_id (file.model, &file.parent, in->id)) giftui_transfer_updownload_add_chunk (in->iface, NULL, &file); } else { gchar *tmp1, *tmp2; file.str_file = interface_get (in->iface, "file"); file.str_hash = interface_get (in->iface, "hash"); file.str_state = interface_get (in->iface, "state"); file.transmit = INTERFACE_GETLU (in->iface, "transmit"); file.status = _state_from_str (file.str_state); file.str_speed = speed_str_human (0); tmp1 = size_str_human (file.transmit); tmp2 = g_strdup_printf ("%s/%s", tmp1, file.str_size); gtk_tree_store_append (GTK_TREE_STORE (file.model), &file.parent, NULL); gtk_tree_store_set (GTK_TREE_STORE (file.model), &file.parent, TRANSFER_FILENAME, file.str_file, TRANSFER_SIZE, tmp2, TRANSFER_PROGRESS, size_percent (file.filesize, file.transmit), TRANSFER_STATE, file.str_state, TRANSFER_HASH, file.str_hash, TRANSFER_FILESIZE, file.filesize, TRANSFER_SPEED, file.str_speed, TRANSFER_TRSPEED, file.speed, TRANSFER_TRANSMIT, file.transmit, TRANSFER_ID, in->id, TRANSFER_COLOR, file.status, TRANSFER_ICON, GTK_STOCK_NEW, -1); interface_foreach (in->iface, NULL, (InterfaceForeach) giftui_transfer_updownload_add_chunk, &file); giftui_child_set_highlight (GIFTUI_CHILD (tr), TRUE); g_free (tmp1); g_free (tmp2); if (file.str_speed) g_free (file.str_speed); } if (file.str_size) g_free (file.str_size); return; } static void giftui_transfer_updownload_update_chunk (Interface *iface, InterfaceNode *inode, GiftuiTransferFile_t *file) { GiftuiTransferChunk_t chunk; if (strcasecmp (inode->key, "SOURCE")) return; memset ((void *) &chunk, 0, sizeof (GiftuiTransferChunk_t)); interface_foreach_ex (iface, inode, (InterfaceForeach) giftui_transferchunk_fill, &chunk); /* Find the good child... */ if (_find_transfer_user (file->model, &file->parent, &file->child, chunk.str_user)) { gulong old_transmit; gtk_tree_model_get (file->model, &file->child, TRANSFER_TRANSMIT, &old_transmit, -1); if (chunk.transmit) { chunk.throughput = chunk.transmit - old_transmit; if (file->elapsed) chunk.speed = (chunk.throughput * 1000) / file->elapsed; } chunk.str_size = size_str_human (chunk.transmit); chunk.str_speed = speed_str_human (chunk.speed); gtk_tree_store_set (GTK_TREE_STORE (file->model), &file->child, TRANSFER_SIZE, chunk.str_size, TRANSFER_TRSPEED, chunk.speed, TRANSFER_PROGRESS, size_percent (file->filesize, chunk.transmit), TRANSFER_START, size_percent (file->filesize, chunk.start), TRANSFER_SPEED, chunk.str_speed, TRANSFER_TRANSMIT, chunk.transmit, TRANSFER_STATE, chunk.str_state, -1); if (chunk.str_size) g_free (chunk.str_size); if (chunk.str_speed) g_free (chunk.str_speed); } return; } void giftui_transfer_updownload_update (GiftuiTransfer *tr, GiftuiEvent_t *in) { GiftuiTransferFile_t file; g_return_if_fail (tr != NULL); g_return_if_fail (in != NULL); memset ((void *) &file, 0, sizeof (GiftuiTransferFile_t)); /* Do we update the up or down list ? */ if (in->type == EVENT_CHGDOWNLOAD) file.model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->down_list)); else if (in->type == EVENT_CHGUPLOAD) file.model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->up_list)); else return; tr->stats_updated = FALSE; /* Find id of transfer. */ if (_find_transfer_id (file.model, &file.parent, in->id)) { gchar *tmp1, *tmp2; gulong old_transmit; file.str_state = interface_get (in->iface, "state"); file.str_file = interface_get (in->iface, "file"); file.filesize = INTERFACE_GETLU (in->iface, "size"); file.transmit = INTERFACE_GETLU (in->iface, "transmit"); file.elapsed = INTERFACE_GETLU (in->iface, "elapsed"); gtk_tree_model_get (file.model, &file.parent, TRANSFER_TRANSMIT, &old_transmit, -1); if (file.transmit) file.throughput = file.transmit - old_transmit; if (file.elapsed) file.speed = (file.throughput * 1000) / file.elapsed; file.status = _state_from_str (file.str_state); file.str_speed = speed_str_human (file.speed); tmp1 = size_str_human (file.transmit); file.str_size = size_str_human (file.filesize); tmp2 = g_strdup_printf ("%s/%s", tmp1, file.str_size); gtk_tree_store_set (GTK_TREE_STORE (file.model), &file.parent, TRANSFER_SIZE, tmp2, TRANSFER_STATE, file.str_state, TRANSFER_SPEED, file.str_speed, TRANSFER_COLOR, file.status, TRANSFER_PROGRESS, size_percent (file.filesize, file.transmit), TRANSFER_TRSPEED, file.speed, TRANSFER_TRANSMIT, file.transmit, -1); g_free (tmp1); g_free (tmp2); interface_foreach (in->iface, NULL, (InterfaceForeach) giftui_transfer_updownload_update_chunk, &file); if (file.str_speed) g_free (file.str_speed); if (file.str_size) g_free (file.str_size); } return; } void giftui_transfer_updownload_del (GiftuiTransfer *tr, GiftuiEvent_t *in) { guint id; GtkTreeIter parent; GtkTreeModel *model; g_return_if_fail (tr != NULL); g_return_if_fail (in != NULL); if (in->type == EVENT_DELDOWNLOAD || in->type == EVENT_DELSOURCE) model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->down_list)); else if (in->type == EVENT_DELUPLOAD) model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->up_list)); else return; tr->stats_updated = FALSE; id = (unsigned int) atoi (in->iface->value); if (_find_transfer_id (model, &parent, id)) { GtkTreeIter child; if (in->type == EVENT_DELSOURCE) { gchar *user; user = interface_get (in->iface, "user"); if (_find_transfer_user (model, &parent, &child, user)) gtk_tree_store_remove (GTK_TREE_STORE (model), &child); } else { gulong transmit, size; gtk_tree_store_remove_children (GTK_TREE_STORE (model), &parent); gtk_tree_model_get (model, &parent, TRANSFER_FILESIZE, &size, TRANSFER_TRANSMIT, &transmit, -1); if (size == transmit) { if (giftui_config_get_bool (PREFS_TRANSFERS_CLEAR_COMPLETED)) gtk_tree_store_remove (GTK_TREE_STORE (model), &parent); else { gtk_tree_store_set (GTK_TREE_STORE (model), &parent, TRANSFER_ID, 0, TRANSFER_SPEED, _("0K/s"), TRANSFER_TRSPEED, 0, -1); gtk_tree_store_set (GTK_TREE_STORE (model), &parent, TRANSFER_STATE, _("Completed"), TRANSFER_COLOR, GTK_CELL_RENDERER_PROGRESS_COMPLETED, -1); } } else { if (giftui_config_get_bool (PREFS_TRANSFERS_CLEAR_CANCELED)) gtk_tree_store_remove (GTK_TREE_STORE (model), &parent); else { gtk_tree_store_set (GTK_TREE_STORE (model), &parent, TRANSFER_ID, 0, TRANSFER_SPEED, _("0K/s"), TRANSFER_TRSPEED, 0, -1); gtk_tree_store_set (GTK_TREE_STORE (model), &parent, TRANSFER_STATE, _("Canceled"), TRANSFER_COLOR, GTK_CELL_RENDERER_PROGRESS_CANCELED, -1); } } giftui_child_set_highlight (GIFTUI_CHILD (tr), TRUE); } } return; } void giftui_transfer_locate_sources (GiftuiTransfer *tr, GiftuiEvent_t *in) { GtkTreeModel *model; GiftuiTransferFile_t file; g_return_if_fail (tr != NULL); g_return_if_fail (in != NULL); memset (&file, 0, sizeof (GiftuiTransferFile_t)); file.str_user = interface_get (in->iface, "user"); if (file.str_user) { GtkTreeIter parent, child; model = gtk_tree_view_get_model (GTK_TREE_VIEW (tr->down_list)); file.str_hash = interface_get (in->iface, "hash"); file.filesize = INTERFACE_GETLU (in->iface, "size"); file.str_url = interface_get (in->iface, "url"); if (_find_transfer_file (model, &parent, file.filesize, file.str_hash) && !_find_transfer_user (model, &parent, &child, file.str_user)) { gtk_tree_model_get (model, &parent, TRANSFER_FILENAME, &file.str_file, -1); giftui_transferfile_download (&file); g_free (file.str_file); } } else giftui_event_unregister (tr, EVENT_ITEM, in->id); return; } /**/ static void giftui_transfer_update_colors_list (GtkTreeView *treeview) { GList *render_list; GObject *obj; GdkColor c; GtkTreeViewColumn *column; column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), TRANSFER_PROGRESS); render_list = gtk_tree_view_column_get_cell_renderers (column); /* There should be only one renderer */ while (render_list) { obj = G_OBJECT (render_list->data); /* Checking for the good renderer */ if (obj && (G_OBJECT_TYPE (obj) == GTK_TYPE_CELL_RENDERER_PROGRESS)) { if (str_to_color (&c, giftui_config_get_str (PREFS_TRANSFERS_ACTIVE_COLOR))) g_object_set (obj, "progressground_active_gdk", &c, NULL); if (str_to_color (&c, giftui_config_get_str (PREFS_TRANSFERS_COMPLETED_COLOR))) g_object_set (obj, "progressground_completed_gdk", &c, NULL); if (str_to_color (&c, giftui_config_get_str (PREFS_TRANSFERS_PAUSED_COLOR))) g_object_set (obj, "progressground_paused_gdk", &c, NULL); if (str_to_color (&c, giftui_config_get_str (PREFS_TRANSFERS_CANCELED_COLOR))) g_object_set (obj, "progressground_canceled_gdk", &c, NULL); } render_list = render_list->next; } return; } void giftui_transfer_update_colors (GiftuiTransfer *tr) { g_return_if_fail (tr != NULL); giftui_transfer_update_colors_list (GTK_TREE_VIEW (tr->down_list)); giftui_transfer_update_colors_list (GTK_TREE_VIEW (tr->up_list)); return; }