summaryrefslogtreecommitdiff
path: root/src/trg-files-model.c
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2012-01-09 21:47:06 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2012-01-09 21:47:06 +0000
commitc0e12ac389135850dcd45ce108f5a6a0200ae03f (patch)
treee7ab9b938e2909f7a40d8fd34a476e301a511052 /src/trg-files-model.c
parente1b13312f975f38d3d7437f28299912eff6947e0 (diff)
issue 174 - exec crash, issue 173 - files first update performance fixed.
Diffstat (limited to 'src/trg-files-model.c')
-rw-r--r--src/trg-files-model.c239
1 files changed, 125 insertions, 114 deletions
diff --git a/src/trg-files-model.c b/src/trg-files-model.c
index 2280d49..521f99b 100644
--- a/src/trg-files-model.c
+++ b/src/trg-files-model.c
@@ -24,6 +24,7 @@
#include "protocol-constants.h"
#include "trg-files-model-common.h"
#include "trg-files-tree-view-common.h"
+#include "trg-files-tree.h"
#include "trg-files-model.h"
#include "trg-client.h"
#include "torrent.h"
@@ -65,105 +66,136 @@ static void trg_files_update_parent_progress(GtkTreeModel * model,
newCompleted = lastCompleted + increment;
gtk_tree_store_set(GTK_TREE_STORE(model), &tmp_iter,
- FILESCOL_BYTESCOMPLETED, newCompleted,
FILESCOL_PROGRESS, file_get_progress(length,
newCompleted),
+ FILESCOL_BYTESCOMPLETED, newCompleted,
-1);
back_iter = tmp_iter;
}
}
-static void trg_files_model_iter_new(TrgFilesModel * model,
- GtkTreeIter * iter, JsonObject * file,
- gint id)
+static void trg_files_tree_update_ancestors(
+ trg_files_tree_node *node)
{
- TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
- gchar **elements = g_strsplit(file_get_name(file), "/", -1);
- gchar *existingName;
- gint i, existingId;
- GtkTreeRowReference *parentRowRef = NULL;
- GtkTreeIter parentIter;
-
- for (i = 0; elements[i]; i++) {
- GtkTreeIter *found = NULL;
+ trg_files_tree_node *back_iter = node;
+ gint pri_result = node->priority;
+ gint enabled_result = node->enabled;
+
+ while ((back_iter = back_iter->parent)) {
+ GList *li;
+ for (li = back_iter->children; li; li = g_list_next(li)) {
+ trg_files_tree_node *back_node = (trg_files_tree_node*)li->data;
+ gboolean stop = FALSE;
+
+ if (back_node->priority != pri_result) {
+ pri_result = TR_PRI_MIXED;
+ stop = TRUE;
+ }
- if (parentRowRef)
- rowref_to_iter(GTK_TREE_MODEL(model), parentRowRef,
- &parentIter);
+ if (back_node->enabled != enabled_result) {
+ enabled_result = TR_PRI_MIXED;
+ stop = TRUE;
+ }
- /* If this is the last component of the path, create a file node. */
+ if (stop)
+ break;
+ }
- if (!elements[i + 1]) {
- gtk_tree_store_append(GTK_TREE_STORE(model), iter,
- parentRowRef ? &parentIter : NULL);
- gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_NAME,
- elements[i], FILESCOL_SIZE,
- file_get_length(file), FILESCOL_ID, id, -1);
+ back_iter->bytesCompleted += node->bytesCompleted;
+ back_iter->length += node->length;
+ back_iter->priority = pri_result;
+ back_iter->enabled = enabled_result;
+ }
+}
- if (parentRowRef)
- trg_files_model_update_parents(GTK_TREE_MODEL(model), iter,
- FILESCOL_SIZE);
+static void store_add_node(GtkTreeStore * store, GtkTreeIter * parent,
+ trg_files_tree_node * node)
+{
+ GtkTreeIter child;
+ GList *li;
+
+ if (node->name) {
+ gdouble progress = file_get_progress(node->length, node->bytesCompleted);
+ gtk_tree_store_append(store, &child, parent);
+ gtk_tree_store_set(store, &child, FILESCOL_WANTED, node->enabled,
+ FILESCOL_PROGRESS, progress,
+ FILESCOL_SIZE, node->length,
+ FILESCOL_ID, node->children ? -1 : node->index,
+ FILESCOL_PRIORITY, node->priority, FILESCOL_NAME, node->name,
+ -1);
+ }
- break;
- }
+ for (li = node->children; li; li = g_list_next(li))
+ store_add_node(store, node->name ? &child : NULL,
+ (trg_files_tree_node *) li->data);
+}
- /* Search for the directory this files goes under, under the saved
- * GtkTreeRowReferece *parent. */
-
- if (gtk_tree_model_iter_children(GTK_TREE_MODEL(model), iter,
- parentRowRef ? &parentIter :
- NULL)) {
- do {
- gtk_tree_model_get(GTK_TREE_MODEL(model), iter,
- FILESCOL_NAME, &existingName,
- FILESCOL_ID, &existingId, -1);
-
- if (existingId == -1
- && !g_strcmp0(elements[i], existingName)) {
- found = iter;
- iter_to_row_reference(GTK_TREE_MODEL(model), iter,
- &parentRowRef);
- }
-
- g_free(existingName);
-
- if (found)
- break;
- } while (gtk_tree_model_iter_next
- (GTK_TREE_MODEL(model), iter));
+static trg_files_tree_node
+ * trg_file_parser_node_insert(trg_files_tree_node * top,
+ trg_files_tree_node * last,
+ JsonObject *file, gint index,
+ JsonArray *enabled, JsonArray *priorities)
+{
+ gchar **path = g_strsplit(file_get_name(file), "/", -1);
+ trg_files_tree_node *lastIter = last;
+ GList *parentList = NULL;
+ gchar *path_el;
+ GList *li;
+ int i;
+
+ if (lastIter)
+ while ((lastIter = lastIter->parent))
+ parentList = g_list_prepend(parentList, lastIter);
+
+ li = parentList;
+ lastIter = NULL;
+
+ /* Iterate over the path list which contains each file/directory
+ * component of the path in order.
+ */
+ for (i = 0; (path_el = path[i]); i++) {
+ gboolean isFile = !path[i + 1];
+ trg_files_tree_node *target_node = NULL;
+
+ if (li && !isFile) {
+ trg_files_tree_node *lastPathNode =
+ (trg_files_tree_node *) li->data;
+
+ if (!g_strcmp0(lastPathNode->name, path[i]))
+ target_node = lastPathNode;
+
+ li = g_list_next(li);
}
- if (!found) {
- GValue gvalue = { 0 };
+ if (!target_node) {
+ target_node = g_new0(trg_files_tree_node, 1);
+ target_node->name = g_strdup(path[i]);
+ target_node->parent = lastIter;
- gtk_tree_store_append(GTK_TREE_STORE(model), iter,
- parentRowRef ? &parentIter : NULL);
- gtk_tree_store_set(GTK_TREE_STORE(model), iter,
- FILESCOL_PRIORITY, TR_PRI_UNSET,
- FILESCOL_NAME, elements[i], -1);
+ if (lastIter)
+ lastIter->children =
+ g_list_append(lastIter->children, target_node);
+ else
+ top->children = g_list_append(top->children, target_node);
+ }
- g_value_init(&gvalue, G_TYPE_INT);
- g_value_set_int(&gvalue, -1);
- gtk_tree_store_set_value(GTK_TREE_STORE(model), iter,
- FILESCOL_ID, &gvalue);
+ lastIter = target_node;
- memset(&gvalue, 0, sizeof(GValue));
- g_value_init(&gvalue, G_TYPE_INT);
- g_value_set_int(&gvalue, TR_PRI_UNSET);
- gtk_tree_store_set_value(GTK_TREE_STORE(model), iter,
- FILESCOL_PRIORITY, &gvalue);
+ if (isFile) {
+ target_node->length = file_get_length(file);
+ target_node->bytesCompleted = file_get_bytes_completed(file);
+ target_node->index = index;
+ target_node->enabled = (gint)json_array_get_int_element(enabled, index);
+ target_node->priority = (gint)json_array_get_int_element(priorities, index);
- iter_to_row_reference(GTK_TREE_MODEL(model), iter,
- &parentRowRef);
+ trg_files_tree_update_ancestors(target_node);
}
}
- if (parentRowRef)
- gtk_tree_row_reference_free(parentRowRef);
+ g_list_free(parentList);
- g_strfreev(elements);
- priv->n_items++;
+ return lastIter;
}
void trg_files_model_set_accept(TrgFilesModel * model, gboolean accept)
@@ -174,17 +206,15 @@ void trg_files_model_set_accept(TrgFilesModel * model, gboolean accept)
static void trg_files_model_iter_update(TrgFilesModel * model,
GtkTreeIter * filesIter,
- gboolean isFirst,
JsonObject * file,
JsonArray * wantedArray,
JsonArray * prioritiesArray,
- int id)
+ gint id)
{
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
-
gint64 fileLength = file_get_length(file);
gint64 fileCompleted = file_get_bytes_completed(file);
- gint64 increment;
+ gint64 lastCompleted;
gboolean wanted =
json_node_get_int(json_array_get_element(wantedArray, id))
@@ -193,36 +223,20 @@ static void trg_files_model_iter_update(TrgFilesModel * model,
json_node_get_int(json_array_get_element(prioritiesArray, id));
gdouble progress = file_get_progress(fileLength, fileCompleted);
- if (isFirst) {
- increment = fileCompleted;
- } else {
- gint64 lastCompleted;
- gtk_tree_model_get(GTK_TREE_MODEL(model), filesIter,
+ gtk_tree_model_get(GTK_TREE_MODEL(model), filesIter,
FILESCOL_BYTESCOMPLETED, &lastCompleted, -1);
- increment = fileCompleted - lastCompleted;
- }
gtk_tree_store_set(GTK_TREE_STORE(model), filesIter, FILESCOL_PROGRESS,
progress, FILESCOL_BYTESCOMPLETED, fileCompleted,
-1);
trg_files_update_parent_progress(GTK_TREE_MODEL(model), filesIter,
- increment);
+ fileCompleted - lastCompleted);
if (priv->accept)
gtk_tree_store_set(GTK_TREE_STORE(model), filesIter,
FILESCOL_WANTED, wanted, FILESCOL_PRIORITY,
priority, -1);
-
- if (isFirst) {
- trg_files_tree_model_propogate_change_up(GTK_TREE_MODEL(model),
- filesIter,
- FILESCOL_PRIORITY,
- priority);
- trg_files_tree_model_propogate_change_up(GTK_TREE_MODEL(model),
- filesIter,
- FILESCOL_WANTED, wanted);
- }
}
static void trg_files_model_class_init(TrgFilesModelClass * klass)
@@ -261,7 +275,7 @@ gboolean trg_files_model_update_foreach(GtkListStore * model,
if (id >= 0) {
file = json_node_get_object(g_list_nth_data(files, id));
- trg_files_model_iter_update(TRG_FILES_MODEL(model), iter, FALSE,
+ trg_files_model_iter_update(TRG_FILES_MODEL(model), iter,
file, priv->wanted, priv->priorities,
id);
}
@@ -274,42 +288,39 @@ void trg_files_model_update(TrgFilesModel * model, gint64 updateSerial,
{
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
GList *filesList, *li;
- GtkTreeIter filesIter;
JsonObject *file;
gint j = 0;
+ guint n_updates;
priv->torrentId = torrent_get_id(t);
priv->priorities = torrent_get_priorities(t);
priv->wanted = torrent_get_wanted(t);
filesList = json_array_get_elements(torrent_get_files(t));
+ n_updates = g_list_length(filesList);
- if (mode == TORRENT_GET_MODE_FIRST) {
+ if (mode == TORRENT_GET_MODE_FIRST || priv->n_items != n_updates) {
+ trg_files_tree_node *top_node = g_new0(trg_files_tree_node, 1);
+ trg_files_tree_node *lastNode = NULL;
gtk_tree_store_clear(GTK_TREE_STORE(model));
priv->accept = TRUE;
+
for (li = filesList; li; li = g_list_next(li)) {
file = json_node_get_object((JsonNode *) li->data);
- trg_files_model_iter_new(model, &filesIter, file, j);
- trg_files_model_iter_update(model, &filesIter, TRUE, file,
- priv->wanted, priv->priorities, j);
- j++;
+ lastNode =
+ trg_file_parser_node_insert(top_node, lastNode,
+ file, j++, priv->wanted, priv->priorities);
}
+
+ priv->n_items = j;
+
+ store_add_node(GTK_TREE_STORE(model), NULL, top_node);
+
} else {
- guint n_updates = g_list_length(filesList);
gtk_tree_model_foreach(GTK_TREE_MODEL(model),
(GtkTreeModelForeachFunc)
trg_files_model_update_foreach, filesList);
- if (n_updates > priv->n_items) {
- gint n_new = n_updates - priv->n_items;
- for (j = n_updates - n_new; j < n_updates; j++) {
- file = json_node_get_object(g_list_nth_data(filesList, j));
- trg_files_model_iter_new(model, &filesIter, file, j);
- trg_files_model_iter_update(model, &filesIter, TRUE, file,
- priv->wanted, priv->priorities,
- j);
- }
- }
}
g_list_free(filesList);