Statistics
| Revision:

root / trunk / client / gui / par2.c @ 1863

History | View | Annotate | Download (28.5 KB)

1
/* 
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#include 
20
#include 
21
#include "gui.h"
22

                
23
static GtkWidget *treeviewPAR2AndUnpack = NULL;
24
static GtkTreeStore *store = NULL;
25
static GList *items_to_pulse = NULL;
26

                
27
enum {
28
    ACTION_PAR2,
29
    ACTION_UNPACK,
30
};
31

                
32
enum {
33
    FIELD_COLLECTION_NAME,
34
    FIELD_COLLECTION_NAME_HASH,
35
    FIELD_ACTION,
36
    FIELD_ACTION_STR,
37
    FIELD_PAR2_OR_UNPACK_FILENAME,
38
    FIELD_FILENAME,
39
    FIELD_FILENAME_HASH,
40
    FIELD_PROGRESS_VALUE,
41
    FIELD_PROGRESS_STR,
42
    FIELD_PROGRESS_PULSE,
43
    LAST_FIELD,
44
};
45

                
46
static gboolean
47
lookup_collection(const char *collection_name, GtkTreeIter *collection_iter)
48
{
49
    GtkTreeIter iter;
50
    guint hash;
51

                
52
    if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) {
53
        return FALSE;
54
    }
55

                
56
    hash = g_str_hash(collection_name);
57
    do {
58
        guint hash_row = 0;
59

                
60
        gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FIELD_COLLECTION_NAME_HASH, &hash_row, -1);
61

                
62
        if (hash == hash_row) {
63
            /* Also verify the collection name itself to be sure */
64
            char *collection_name_row = NULL;
65

                
66
            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FIELD_COLLECTION_NAME, &collection_name_row, -1);
67

                
68
            if (!strcmp(collection_name, collection_name_row)) {
69
                *collection_iter = iter;
70
                g_free(collection_name_row);
71
                return TRUE;
72
            }
73

                
74
            g_free(collection_name_row);
75
        }
76
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
77

                
78
    return FALSE;
79
}
80

                
81
static gboolean
82
lookup_filename(GtkTreeIter parent_iter, const char *filename, GtkTreeIter *filename_iter)
83
{
84
    GtkTreeIter iter;
85
    guint hash;
86

                
87
    if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, &parent_iter)) {
88
        return FALSE;
89
    }
90

                
91
    hash = g_str_hash(filename);
92
    do {
93
        guint hash_row = 0;
94

                
95
        gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FIELD_FILENAME_HASH, &hash_row, -1);
96

                
97
        if (hash == hash_row) {
98
            /* Also verify the filename itself to be sure */
99
            char *filename_row = NULL;
100

                
101
            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FIELD_FILENAME, &filename_row, -1);
102

                
103
            if (!strcmp(filename, filename_row)) {
104
                *filename_iter = iter;
105
                g_free(filename_row);
106
                return TRUE;
107
            }
108

                
109
            g_free(filename_row);
110
        }
111
    } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
112

                
113
    return FALSE;
114
}
115

                
116
static void
117
scroll_to_bottom(GtkTreeIter iter)
118
{
119
    GtkTreePath *path;
120

                
121
    gtk_tree_view_expand_all(GTK_TREE_VIEW(treeviewPAR2AndUnpack));
122
    path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
123
    gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(treeviewPAR2AndUnpack), path, NULL, FALSE, 0.0, 0.0);
124
    gtk_tree_path_free(path);
125
}
126

                
127
static void
128
par2_begin_verify (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, gpointer data)
129
{
130
    GtkTreeIter collection_iter;
131
    GtkTreeIter par2set_iter;
132
    GtkTreePath *path;
133
    char *filename = g_path_get_basename(active_par2_filename);
134

                
135
    if (!lookup_collection(collection_name, &collection_iter)) {
136
        /* Collection not found yet, create a new entry */
137
        gtk_tree_store_append(store, &collection_iter, NULL);
138
        gtk_tree_store_set(store, &collection_iter, FIELD_COLLECTION_NAME, collection_name,
139
                                                    FIELD_COLLECTION_NAME_HASH, g_str_hash(collection_name),
140
                                                    FIELD_FILENAME, collection_name,
141
                                                    FIELD_PROGRESS_PULSE, 1,
142
                                                    FIELD_PROGRESS_STR, "",
143
                                                    -1);
144

                
145
        path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &collection_iter);
146
        items_to_pulse = g_list_prepend(items_to_pulse, gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path));
147
        gtk_tree_path_free(path);
148
    }
149

                
150
    if (lookup_filename(collection_iter, filename, &par2set_iter)) {
151
        /* PAR2 set was already found, clear all the previous contents */
152
        gtk_tree_store_remove(store, &par2set_iter);
153
        memset(&par2set_iter, 0, sizeof(par2set_iter));
154
    }
155

                
156
    gtk_tree_store_append(store, &par2set_iter, &collection_iter);
157
    scroll_to_bottom(par2set_iter);
158
    gtk_tree_store_set(store, &par2set_iter,    FIELD_FILENAME, filename,
159
                                                FIELD_FILENAME_HASH, g_str_hash(filename),
160
                                                FIELD_PAR2_OR_UNPACK_FILENAME, filename,
161
                                                FIELD_ACTION, ACTION_PAR2,
162
                                                FIELD_ACTION_STR, _("PAR2 repair"),
163
                                                FIELD_PROGRESS_STR, _("Now verifying files"),
164
                                                FIELD_PROGRESS_PULSE, 1,
165
                                                -1);
166

                
167
    path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &par2set_iter);
168
    items_to_pulse = g_list_prepend(items_to_pulse, gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path));
169
    gtk_tree_path_free(path);
170

                
171
    g_free(filename);
172
}
173

                
174
static void
175
par2_load_progress_update (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, const char *filename, double progress, gpointer data)
176
{
177
    GtkTreeIter collection_iter;
178
    GtkTreeIter par2set_iter;
179
    GtkTreeIter filename_iter;
180
    char *par2_filename = g_path_get_basename(active_par2_filename);
181

                
182
    if (!lookup_collection(collection_name, &collection_iter)) {
183
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
184
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
185
    }
186

                
187
    if (!lookup_filename(collection_iter, par2_filename, &par2set_iter)) {
188
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
189
        g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
190
    }
191

                
192
    if (lookup_filename(par2set_iter, filename, &filename_iter)) {
193
        /* Update the contents of the row */
194
        gtk_tree_store_set(store, &filename_iter, FIELD_PROGRESS_VALUE, (int) (progress), -1);
195
    } else {
196
        gtk_tree_store_append(store, &filename_iter, &par2set_iter);
197
        scroll_to_bottom(filename_iter);
198
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, filename,
199
                                                    FIELD_FILENAME_HASH, g_str_hash(filename),
200
                                                    FIELD_PROGRESS_VALUE, (int) (progress),
201
                                                    FIELD_PROGRESS_PULSE, -1,
202
                                                    -1);
203
    }
204

                
205
    g_free(par2_filename);
206
}
207

                
208
static void
209
par2_recovery_file_loaded (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, const char *filename, int num_new_packets, int num_blocks_found, gpointer data)
210
{
211
    GtkTreeIter collection_iter;
212
    GtkTreeIter par2set_iter;
213
    GtkTreeIter filename_iter;
214
    char *msg;
215
    char *par2_filename = g_path_get_basename(active_par2_filename);
216

                
217
    if (!lookup_collection(collection_name, &collection_iter)) {
218
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
219
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
220
    }
221

                
222
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
223

                
224
    msg = g_strdup_printf(_("%i new PAR2 recovery blocks found"), num_blocks_found);
225
    if (lookup_filename(par2set_iter, filename, &filename_iter)) {
226
        /* Update the contents of the row */
227
        gtk_tree_store_set(store, &filename_iter,   FIELD_PROGRESS_VALUE, 100,
228
                                                    FIELD_PROGRESS_STR, msg,
229
                                                    -1);
230
    } else {
231
        gtk_tree_store_append(store, &filename_iter, &par2set_iter);
232
        scroll_to_bottom(filename_iter);
233
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, filename,
234
                                                    FIELD_FILENAME_HASH, g_str_hash(filename),
235
                                                    FIELD_PROGRESS_VALUE, 100,
236
                                                    FIELD_PROGRESS_STR, msg,
237
                                                    FIELD_PROGRESS_PULSE, -1,
238
                                                    -1);
239
    }
240

                
241
    g_free(msg);
242
    g_free(par2_filename);
243

                
244
    // TODO: Process num_new_packets
245
}
246

                
247
static void
248
par2_file_loaded (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, const char *filename, const char *state, int num_blocks_found, int num_blocks_expected, gpointer data)
249
{
250
    GtkTreeIter collection_iter;
251
    GtkTreeIter par2set_iter;
252
    GtkTreeIter filename_iter;
253
    char *msg;
254
    int progress;
255
    char *par2_filename = g_path_get_basename(active_par2_filename);
256

                
257
    if (!lookup_collection(collection_name, &collection_iter)) {
258
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
259
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
260
    }
261

                
262
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
263

                
264
    if (!strcmp(state, "MISSING")) {
265
        msg = g_strdup(_("File is missing"));
266
        progress = 0;
267
    } else if (!strcmp(state, "NO_NEW_BLOCKS_FOUND")) {
268
        msg = g_strdup(_("No new blocks found"));
269
        progress = 100;
270
    } else if (num_blocks_expected == num_blocks_found) {
271
        progress = 100;
272
        msg = g_strdup(_("File is complete"));
273
    } else {
274
        double progress_tmp = num_blocks_found;
275
        progress_tmp /= num_blocks_expected;
276
        progress_tmp *= 100.0;
277
        progress = (int) progress_tmp;
278
        msg = g_strdup_printf(_("%i blocks found (expected: %i)"), num_blocks_found, num_blocks_expected);
279
    }
280

                
281
    if (lookup_filename(par2set_iter, filename, &filename_iter)) {
282
        /* Update the contents of the row */
283
        gtk_tree_store_set(store, &filename_iter,   FIELD_PROGRESS_VALUE, progress,
284
                                                    FIELD_PROGRESS_STR, msg,
285
                                                    FIELD_PROGRESS_PULSE, -1,
286
                                                    -1);
287
    } else {
288
        gtk_tree_store_append(store, &filename_iter, &par2set_iter);
289
        scroll_to_bottom(filename_iter);
290
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, filename,
291
                                                    FIELD_FILENAME_HASH, g_str_hash(filename),
292
                                                    FIELD_PROGRESS_VALUE, progress,
293
                                                    FIELD_PROGRESS_STR, msg,
294
                                                    FIELD_PROGRESS_PULSE, -1,
295
                                                    -1);
296
    }
297

                
298
    g_free(msg);
299
    g_free(par2_filename);
300

                
301
    // TODO: Update the row of the PAR2 set itself with the new progress
302
}
303

                
304
static void
305
par2_repair_progress_update (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, double progress, gpointer data)
306
{
307
    GtkTreeIter collection_iter;
308
    GtkTreeIter par2set_iter;
309
    char *par2_filename = g_path_get_basename(active_par2_filename);
310

                
311
    if (!lookup_collection(collection_name, &collection_iter)) {
312
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
313
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
314
    }
315

                
316
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
317

                
318
    gtk_tree_store_set(store, &par2set_iter,    FIELD_PROGRESS_VALUE, (int) (progress),
319
                                                FIELD_PROGRESS_STR, _("Repairing"),
320
                                                FIELD_PROGRESS_PULSE, -1,
321
                                                -1);
322

                
323
    g_free(par2_filename);
324
}
325

                
326
static void
327
par2_repair_failure (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, const char *message, int num_blocks_more_required, gpointer data)
328
{
329
    GtkTreeIter collection_iter;
330
    GtkTreeIter par2set_iter;
331
    char *msg;
332
    char *par2_filename = g_path_get_basename(active_par2_filename);
333

                
334
    if (!lookup_collection(collection_name, &collection_iter)) {
335
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
336
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
337
    }
338

                
339
    gtk_tree_store_set(store, &collection_iter, FIELD_PROGRESS_PULSE, -1, -1);
340

                
341
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
342

                
343
    if (num_blocks_more_required == -1) {
344
        msg = g_strdup(message);
345
    } else {
346
        msg = g_strdup_printf(_("PAR2 repair failed: %i more blocks required"), num_blocks_more_required);
347
    }
348

                
349
    gtk_tree_store_set(store, &par2set_iter,    FIELD_PROGRESS_VALUE, 100,
350
                                                FIELD_PROGRESS_STR, msg,
351
                                                FIELD_PROGRESS_PULSE, -1,
352
                                                -1);
353
    g_free(msg);
354
    g_free(par2_filename);
355
}
356

                
357
static void
358
par2_repair_success (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, gpointer data)
359
{
360
    GtkTreeIter collection_iter;
361
    GtkTreeIter par2set_iter;
362
    char *par2_filename = g_path_get_basename(active_par2_filename);
363

                
364
    if (!lookup_collection(collection_name, &collection_iter)) {
365
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
366
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
367
    }
368

                
369
    gtk_tree_store_set(store, &collection_iter, FIELD_PROGRESS_PULSE, -1, -1);
370

                
371
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
372

                
373
    gtk_tree_store_set(store, &par2set_iter,    FIELD_PROGRESS_VALUE, 100,
374
                                                FIELD_PROGRESS_STR, _("PAR2 repair succeeded"),
375
                                                FIELD_PROGRESS_PULSE, -1,
376
                                                -1);
377

                
378
    g_free(par2_filename);
379
}
380

                
381
static void
382
par2_no_repair_required (NntpgrabGlue *obj, const char *collection_name, const char *active_par2_filename, gpointer data)
383
{
384
    GtkTreeIter collection_iter;
385
    GtkTreeIter par2set_iter;
386
    char *par2_filename = g_path_get_basename(active_par2_filename);
387

                
388
    if (!lookup_collection(collection_name, &collection_iter)) {
389
        par2_begin_verify(glue, collection_name, active_par2_filename, data);
390
        g_return_if_fail(lookup_collection(collection_name, &collection_iter));
391
    }
392

                
393
    gtk_tree_store_set(store, &collection_iter, FIELD_PROGRESS_PULSE, -1, -1);
394

                
395
    g_return_if_fail(lookup_filename(collection_iter, par2_filename, &par2set_iter));
396

                
397
    gtk_tree_store_set(store, &par2set_iter,    FIELD_PROGRESS_VALUE, 100,
398
                                                FIELD_PROGRESS_STR, _("No repair needed"),
399
                                                FIELD_PROGRESS_PULSE, -1,
400
                                                -1);
401

                
402
    g_free(par2_filename);
403
}
404

                
405
static void
406
unpack_progress_update (NntpgrabGlue *obj, const char *collection_name, const char *filename, double progress, gpointer data)
407
{
408
    GtkTreeIter collection_iter;
409
    GtkTreeIter filename_iter;
410
    int pulse = -1;
411
    char *unpack_filename = g_path_get_basename(filename);
412

                
413
    if (!lookup_collection(collection_name, &collection_iter)) {
414
        /* Collection not found yet, create a new entry */
415
        gtk_tree_store_append(store, &collection_iter, NULL);
416
        gtk_tree_store_set(store, &collection_iter, FIELD_COLLECTION_NAME, collection_name,
417
                                                    FIELD_COLLECTION_NAME_HASH, g_str_hash(collection_name),
418
                                                    FIELD_FILENAME, collection_name,
419
                                                    FIELD_PROGRESS_STR, "",
420
                                                    -1);
421
    }
422

                
423
    if (progress <= 0 ) {
424
        GtkTreePath *path;
425

                
426
        progress = 0;
427
        pulse = 1;
428

                
429
        gtk_tree_store_set(store, &collection_iter, FIELD_PROGRESS_PULSE, pulse, -1);
430

                
431
        path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &collection_iter);
432
        items_to_pulse = g_list_prepend(items_to_pulse, gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path));
433
        gtk_tree_path_free(path);
434
    }
435

                
436
    if (progress == 1.0) {
437
        gtk_tree_store_set(store, &collection_iter, FIELD_PROGRESS_PULSE, -1, -1);
438
    }
439

                
440
    if (lookup_filename(collection_iter, unpack_filename, &filename_iter)) {
441
        /* Unpack file was already found yet, update it */
442
        gtk_tree_store_set(store, &filename_iter,   FIELD_PROGRESS_VALUE, (int) (progress * 100),
443
                                                    FIELD_PROGRESS_PULSE, pulse,
444
                                                    -1);
445

                
446
        if (progress == 1.0) {
447
            gtk_tree_store_set(store, &filename_iter, FIELD_PROGRESS_STR, _("Unpack completed"), -1);
448
        }
449
    } else {
450
        /* Create a new entry */
451
        gtk_tree_store_append(store, &filename_iter, &collection_iter);
452
        scroll_to_bottom(filename_iter);
453
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, unpack_filename,
454
                                                    FIELD_FILENAME_HASH, g_str_hash(unpack_filename),
455
                                                    FIELD_PAR2_OR_UNPACK_FILENAME, unpack_filename,
456
                                                    FIELD_ACTION, ACTION_UNPACK,
457
                                                    FIELD_ACTION_STR, _("Unpack"),
458
                                                    FIELD_PROGRESS_VALUE, (int) (progress * 100),
459
                                                    FIELD_PROGRESS_STR, _("Now unpacking"),
460
                                                    FIELD_PROGRESS_PULSE, pulse,
461
                                                    -1);
462
    }
463

                
464
    if (pulse > 0) {
465
        GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &filename_iter);
466
        items_to_pulse = g_list_prepend(items_to_pulse, gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path));
467
        gtk_tree_path_free(path);
468
    }
469

                
470
    g_free(unpack_filename);
471
}
472

                
473
static void
474
unpack_message_received (NntpgrabGlue *obj, const char *collection_name, const char *filename, const char *message, gpointer data)
475
{
476
    GtkTreeIter collection_iter;
477
    GtkTreeIter filename_iter;
478
    char *unpack_filename = g_path_get_basename(filename);
479

                
480
    if (!lookup_collection(collection_name, &collection_iter)) {
481
        /* Collection not found yet, create a new entry */
482
        gtk_tree_store_append(store, &collection_iter, NULL);
483
        gtk_tree_store_set(store, &collection_iter, FIELD_COLLECTION_NAME, collection_name,
484
                                                    FIELD_COLLECTION_NAME_HASH, g_str_hash(collection_name),
485
                                                    FIELD_FILENAME, collection_name,
486
                                                    FIELD_PROGRESS_STR, "",
487
                                                    -1);
488
    }
489

                
490
    if (lookup_filename(collection_iter, unpack_filename, &filename_iter)) {
491
        /* Unpack file was already found yet, update it */
492
        gtk_tree_store_set(store, &filename_iter, FIELD_PROGRESS_STR, message, -1);
493
    } else {
494
        /* Create a new entry */
495
        gtk_tree_store_append(store, &filename_iter, &collection_iter);
496
        scroll_to_bottom(filename_iter);
497
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, unpack_filename,
498
                                                    FIELD_FILENAME_HASH, g_str_hash(unpack_filename),
499
                                                    FIELD_PAR2_OR_UNPACK_FILENAME, unpack_filename,
500
                                                    FIELD_ACTION, ACTION_UNPACK,
501
                                                    FIELD_ACTION_STR, _("Unpack"),
502
                                                    FIELD_PROGRESS_STR, message,
503
                                                    -1);
504
    }
505

                
506
    g_free(unpack_filename);
507
}
508

                
509
static void
510
unpack_working_archive_changed (NntpgrabGlue *obj, const char *collection_name, const char *filename, const char *working_archive, gpointer data)
511
{
512
    GtkTreeIter collection_iter;
513
    GtkTreeIter filename_iter;
514
    char *msg;
515
    char *unpack_filename = g_path_get_basename(filename);
516

                
517
    if (!lookup_collection(collection_name, &collection_iter)) {
518
        /* Collection not found yet, create a new entry */
519
        gtk_tree_store_append(store, &collection_iter, NULL);
520
        gtk_tree_store_set(store, &collection_iter, FIELD_COLLECTION_NAME, collection_name,
521
                                                    FIELD_COLLECTION_NAME_HASH, g_str_hash(collection_name),
522
                                                    FIELD_FILENAME, collection_name,
523
                                                    FIELD_PROGRESS_STR, "",
524
                                                    -1);
525
    }
526

                
527
    msg = g_strdup_printf(_("Now unpacking archive '%s'"), working_archive);
528
    if (lookup_filename(collection_iter, unpack_filename, &filename_iter)) {
529
        /* Unpack file was already found yet, update it */
530
        gtk_tree_store_set(store, &filename_iter, FIELD_PROGRESS_STR, msg, -1);
531
    } else {
532
        /* Create a new entry */
533
        gtk_tree_store_append(store, &filename_iter, &collection_iter);
534
        scroll_to_bottom(filename_iter);
535
        gtk_tree_store_set(store, &filename_iter,   FIELD_FILENAME, unpack_filename,
536
                                                    FIELD_FILENAME_HASH, g_str_hash(unpack_filename),
537
                                                    FIELD_PAR2_OR_UNPACK_FILENAME, unpack_filename,
538
                                                    FIELD_ACTION, ACTION_UNPACK,
539
                                                    FIELD_ACTION_STR, _("Unpack"),
540
                                                    FIELD_PROGRESS_STR, msg,
541
                                                    -1);
542
    }
543

                
544
    g_free(msg);
545
    g_free(unpack_filename);
546
}
547

                
548
static void
549
plugin_event_cb(NntpgrabGlue *obj, const char *plugin_name, const char *event_name, const char **values, gpointer data)
550
{
551
    if (!strcmp(plugin_name, "PAR2")) {
552
        if (!strcmp(event_name, "par2_begin_verify")) {
553
            par2_begin_verify(glue, values[0], values[1], data);
554
        } else if (!strcmp(event_name, "par2_load_progress_update")) {
555
            par2_load_progress_update(glue, values[0], values[1], values[2], g_ascii_strtod(values[3], NULL), data);
556
        } else if (!strcmp(event_name, "par2_recovery_file_loaded")) {
557
            par2_recovery_file_loaded(glue, values[0], values[1], values[2], atoi(values[3]), atoi(values[4]), data);
558
        } else if (!strcmp(event_name, "par2_file_loaded")) {
559
            par2_file_loaded(glue, values[0], values[1], values[2], values[3], atoi(values[4]), atoi(values[5]), data);
560
        } else if (!strcmp(event_name, "par2_repair_progress_update")) {
561
            par2_repair_progress_update(glue, values[0], values[1], g_ascii_strtod(values[2], NULL), data);
562
        } else if (!strcmp(event_name, "par2_repair_failure")) {
563
            par2_repair_failure(glue, values[0], values[1], values[2], atoi(values[3]), data);
564
        } else if (!strcmp(event_name, "par2_repair_success")) {
565
            par2_repair_success(glue, values[0], values[1], data);
566
        } else if (!strcmp(event_name, "par2_no_repair_required")) {
567
            par2_no_repair_required(glue, values[0], values[1], data);
568
        } else {
569
            g_warning("Unknown plugin event received from %s plugin: %s\n", plugin_name, event_name);
570
        }
571
    } else if (!strcmp(plugin_name, "Unpack")) {
572
        if (!strcmp(event_name, "unpack_progress_update")) {
573
            unpack_progress_update(glue, values[0], values[1], g_ascii_strtod(values[2], NULL), data);
574
        } else if (!strcmp(event_name, "unpack_message_received")) {
575
            unpack_message_received(glue, values[0], values[1], values[2], data);
576
        } else if (!strcmp(event_name, "unpack_working_archive_changed")) {
577
            unpack_working_archive_changed(glue, values[0], values[1], values[2], data);
578
        } else if (!strcmp(event_name, "unpack_success")) {
579
            // already handled in unpack_progress_update
580
        } else if (!strcmp(event_name, "unpack_failure")) {
581
            // already handled in unpack_progress_update
582
        } else {
583
            g_warning("Unknown plugin event received from %s plugin: %s\n", plugin_name, event_name);
584
        }
585
    }
586
}
587

                
588
static gboolean
589
update_items_to_pulse(gpointer data)
590
{
591
    GList *list = items_to_pulse;
592

                
593
    while (list) {
594
        GtkTreeRowReference *ref = list->data;
595
        GtkTreeIter iter;
596
        GtkTreePath *path;
597
        int pulse_val;
598

                
599
        if (!gtk_tree_row_reference_valid(ref)) {
600
            items_to_pulse = list = g_list_remove(items_to_pulse, ref);
601
            gtk_tree_row_reference_free(ref);
602
            continue;
603
        }
604

                
605
        path = gtk_tree_row_reference_get_path(ref);
606
        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path);
607
        gtk_tree_path_free(path);
608

                
609
        gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FIELD_PROGRESS_PULSE, &pulse_val, -1);
610
        if (pulse_val == -1) {
611
            items_to_pulse = list = g_list_remove(items_to_pulse, ref);
612
            gtk_tree_row_reference_free(ref);
613
            continue;
614
        }
615

                
616
        pulse_val++;
617

                
618
        gtk_tree_store_set(store, &iter, FIELD_PROGRESS_PULSE, pulse_val, -1);
619
        list = g_list_next(list);
620
    }
621

                
622
    /* Come back here in a few moments*/
623
    return TRUE;
624
}
625

                
626
void
627
gui_par2_initialize(void)
628
{
629
    GtkCellRenderer *cellRenderer;
630
    GtkTreeViewColumn *col;
631

                
632
    treeviewPAR2AndUnpack = nntpgrab_gui_base_get_widget("treeviewPAR2AndUnpack");
633

                
634
    cellRenderer = gtk_cell_renderer_text_new();
635
    col = gtk_tree_view_column_new_with_attributes(_("Filename"), cellRenderer, "text", 5, NULL);
636
    gtk_tree_view_column_set_resizable(col, TRUE);
637
    gtk_tree_view_column_set_reorderable(col, TRUE);
638
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviewPAR2AndUnpack), col, -1);
639

                
640
    cellRenderer = gtk_cell_renderer_text_new();
641
    col = gtk_tree_view_column_new_with_attributes(_("Action"), cellRenderer, "text", 3, NULL);
642
    gtk_tree_view_column_set_resizable(col, TRUE);
643
    gtk_tree_view_column_set_reorderable(col, TRUE);
644
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviewPAR2AndUnpack), col, -1);
645

                
646
    cellRenderer = gtk_cell_renderer_progress_new();
647
#if GTK_CHECK_VERSION(2,12,0)
648
    col = gtk_tree_view_column_new_with_attributes(_("Progress"), cellRenderer, "value", 7, "text", 8, "pulse", 9, NULL);
649
#else
650
    col = gtk_tree_view_column_new_with_attributes(_("Progress"), cellRenderer, "value", 7, "text", 8, NULL);
651
#endif
652
    gtk_tree_view_column_set_resizable(col, TRUE);
653
    gtk_tree_view_column_set_reorderable(col, TRUE);
654
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeviewPAR2AndUnpack), col, -1);
655

                
656
    store = gtk_tree_store_new (LAST_FIELD,
657
                                G_TYPE_STRING,  /* FIELD_COLLECTION_NAME */
658
                                G_TYPE_UINT,    /* FIELD_COLLECTION_NAME_HASH */
659
                                G_TYPE_INT,     /* FIELD_ACTION */
660
                                G_TYPE_STRING,  /* FIELD_ACTION_STR */
661
                                G_TYPE_STRING,  /* FIELD_PAR2_OR_UNPACK_FILENAME */
662
                                G_TYPE_STRING,  /* FIELD_FILENAME */
663
                                G_TYPE_UINT,    /* FIELD_FILENAME_HASH */
664
                                G_TYPE_INT,     /* FIELD_PROGRESS_VALUE */
665
                                G_TYPE_STRING,  /* FIELD_PROGRESS_STR */
666
                                G_TYPE_UINT    /* FIELD_PROGRESS_PULSE */
667
                               );
668

                
669
    gtk_tree_view_set_model(GTK_TREE_VIEW(treeviewPAR2AndUnpack), GTK_TREE_MODEL(store));
670

                
671
    nntpgrab_glue_signal_connect(glue, "plugin_event", NG_CALLBACK(plugin_event_cb), NULL);
672

                
673
    g_timeout_add(500, update_items_to_pulse, NULL);
674
}