Statistics
| Revision:

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

History | View | Annotate | Download (42 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 "gui.h"
21
#include "nntpgrab_utils.h"
22

                
23
#ifdef HAVE_SOUP
24

                
25
enum {
26
    FIELD_COLLECTION_ID,
27
    FIELD_COLLECTION_NAME,
28
    FIELD_SHORT_COLLECTION_NAME,
29
    FIELD_SUBJECT,
30
    FIELD_POSTER,
31
    FIELD_NEWSGROUP,
32
    FIELD_FILE_ID,
33
    FIELD_FILESIZE_STR,
34
    FIELD_STAMP,
35
    FIELD_STAMP_STR,
36
    FIELD_COMPLETE_PERCENTAGE,
37
    FIELD_SELECTED,
38
    LAST_FIELD
39
};
40
static GtkTreeViewColumn *columns[LAST_FIELD] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
41
static GThreadPool *pool_details = NULL;
42
static NZBCreatorSearchOpts cached_search_opts;
43
static int results_per_page = 0;
44

                
45
// nzb.c
46
gboolean    nzb_perform_quick_import(const char *collection_name, const char *nzb_contents);
47

                
48
static gboolean
49
process_error(gpointer data)
50
{
51
    GtkWidget *btnNZBCreatorPerformSearch = nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch");
52
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
53
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
54
    GtkWidget *expanderNZBCreator = nntpgrab_gui_base_get_widget("expanderNZBCreator");
55
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
56
    GtkWidget *btnNZBCreatorNewerResults = nntpgrab_gui_base_get_widget("btnNZBCreatorNewerResults");
57
    GtkWidget *btnNZBCreatorOlderResults = nntpgrab_gui_base_get_widget("btnNZBCreatorOlderResults");
58
    GtkWidget *btnNZBCreatorSelectAll = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectAll");
59
    GtkWidget *btnNZBCreatorSelectNone = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectNone");
60
    char *msg = (char*) data;
61

                
62
    nntpgrab_gui_base_dialog_show(windowMain, msg, GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
63

                
64
    g_free(msg);
65

                
66
    gtk_widget_set_sensitive(btnNZBCreatorPerformSearch, FALSE);
67
    gtk_widget_set_sensitive(entryNZBCreatorQuery, FALSE);
68
    gtk_widget_set_sensitive(expanderNZBCreator, FALSE);
69
    gtk_widget_set_sensitive(treeNZBCreatorResults, FALSE);
70
    gtk_widget_set_sensitive(btnNZBCreatorNewerResults, FALSE);
71
    gtk_widget_set_sensitive(btnNZBCreatorOlderResults, FALSE);
72
    gtk_widget_set_sensitive(btnNZBCreatorSelectAll, FALSE);
73
    gtk_widget_set_sensitive(btnNZBCreatorSelectNone, FALSE);
74

                
75
    return FALSE;
76
}
77

                
78
static void
79
generate_stamp(time_t stamp, char *buf, int buf_len)
80
{
81
    struct tm *now;
82

                
83
    if ((now = localtime(&stamp)) == NULL) {
84
        // Date could not be parted
85
        buf[0] = '\0';
86
    }
87

                
88
    strftime(buf, buf_len, "%c", now);
89
}
90

                
91
static gboolean
92
process_search_result(gpointer data)
93
{
94
    GtkWidget *btnNZBCreatorPerformSearch = nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch");
95
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
96
    GtkWidget *expanderNZBCreator = nntpgrab_gui_base_get_widget("expanderNZBCreator");
97
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
98
    GtkWidget *btnNZBCreatorNewerResults = nntpgrab_gui_base_get_widget("btnNZBCreatorNewerResults");
99
    GtkWidget *btnNZBCreatorOlderResults = nntpgrab_gui_base_get_widget("btnNZBCreatorOlderResults");
100
    GtkWidget *btnNZBCreatorSelectAll = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectAll");
101
    GtkWidget *btnNZBCreatorSelectNone = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectNone");
102
    NZBCreatorSearchResult *result = (NZBCreatorSearchResult*) data;
103

                
104
    if (result->number_of_results == 0) {
105
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
106
        nntpgrab_gui_base_dialog_show(windowMain, _("No results found"), GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
107
    } else {
108
        NGList *list;
109
        GtkTreeModel *model;
110
        GtkTreeIter iter_parent;
111

                
112
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeNZBCreatorResults));
113

                
114
        list = result->collections;
115
        while (list) {
116
            char filesize[64];
117
            char stamp[64];
118
            NZBCreatorCollection *collection = (NZBCreatorCollection*) list->data;
119

                
120
            memset(&filesize, 0, sizeof(filesize));
121
            nntpgrab_utils_calculate_file_size(collection->total_size, filesize, sizeof(filesize) - 1);
122

                
123
            memset(&stamp, 0, sizeof(stamp));
124
            generate_stamp(collection->stamp, stamp, sizeof(stamp) - 1);
125

                
126
            gtk_tree_store_append(GTK_TREE_STORE(model), &iter_parent, NULL);
127
            gtk_tree_store_set(GTK_TREE_STORE(model), &iter_parent,
128
                                    FIELD_COLLECTION_ID, collection->collection_id,
129
                                    FIELD_COLLECTION_NAME, collection->collection_name,
130
                                    FIELD_SHORT_COLLECTION_NAME, collection->short_collection_name,
131
                                    FIELD_SUBJECT, collection->collection_name,
132
                                    FIELD_POSTER, collection->poster,
133
                                    FIELD_NEWSGROUP, collection->newsgroup,
134
                                    FIELD_STAMP, (int) collection->stamp,
135
                                    FIELD_STAMP_STR, stamp,
136
                                    FIELD_FILESIZE_STR, filesize,
137
                                    FIELD_FILE_ID, collection->first_file_id,
138
                                    -1);
139

                
140
            if (collection->first_file_id == -1) {
141
                /* Show a placeholder item */
142
                GtkTreeIter iter;
143

                
144
                gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &iter_parent);
145
                gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
146
                                   FIELD_SUBJECT, "unknown",
147
                                   -1);
148
            }
149

                
150
            gtk_tree_store_set(GTK_TREE_STORE(model), &iter_parent, FIELD_COMPLETE_PERCENTAGE, collection->complete_percentage, -1);
151

                
152
            list = ng_list_next(list);
153
        }
154

                
155
        gtk_expander_set_expanded(GTK_EXPANDER(expanderNZBCreator), FALSE);
156

                
157
        if (result->number_of_results > result->results_per_page && result->offset + result->results_per_page < result->number_of_results) {
158
            gtk_widget_set_sensitive(btnNZBCreatorOlderResults, TRUE);
159
        }
160

                
161
        gtk_widget_set_sensitive(btnNZBCreatorSelectAll, TRUE);
162
        gtk_widget_set_sensitive(btnNZBCreatorSelectNone, TRUE);
163
    }
164

                
165
    results_per_page = result->results_per_page;
166

                
167
    if (result->offset > 0) {
168
        gtk_widget_set_sensitive(btnNZBCreatorNewerResults, TRUE);
169
    }
170

                
171
    gtk_widget_set_sensitive(btnNZBCreatorPerformSearch, TRUE);
172
    gtk_widget_set_sensitive(entryNZBCreatorQuery, TRUE);
173
    gtk_widget_set_sensitive(expanderNZBCreator, TRUE);
174
    gtk_widget_set_sensitive(treeNZBCreatorResults, TRUE);
175
    return FALSE;
176
}
177

                
178
static gpointer
179
perform_search_func(gpointer data)
180
{
181
    NZBCreatorSearchOpts *opts = (NZBCreatorSearchOpts*) data;
182
    NZBCreatorSearchResult *result;
183
    char *errmsg = NULL;
184

                
185
    result = nntpgrab_utils_nzbcreator_perform_search(*opts, &errmsg);
186
    if (result) {
187
        g_idle_add(process_search_result, result);
188
    } else {
189
        char *msg = g_strdup_printf(_("Error while performing search:\n%s"), errmsg);
190
        g_idle_add(process_error, msg);
191
        g_free(errmsg);
192
    }
193

                
194
    return NULL;
195
}
196

                
197
static void
198
perform_search(void)
199
{
200
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
201
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
202
    GtkWidget *expanderNZBCreator = nntpgrab_gui_base_get_widget("expanderNZBCreator");
203
    GtkWidget *btnNZBCreatorPerformSearch = nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch");
204
    GtkWidget *btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
205
    GtkWidget *btnNZBCreatorNewerResults = nntpgrab_gui_base_get_widget("btnNZBCreatorNewerResults");
206
    GtkWidget *btnNZBCreatorOlderResults = nntpgrab_gui_base_get_widget("btnNZBCreatorOlderResults");
207
    GtkWidget *btnNZBCreatorSelectAll = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectAll");
208
    GtkWidget *btnNZBCreatorSelectNone = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectNone");
209
    GtkTreeModel *model;
210

                
211
    gtk_widget_set_sensitive(expanderNZBCreator, FALSE);
212
    gtk_widget_set_sensitive(entryNZBCreatorQuery, FALSE);
213
    gtk_widget_set_sensitive(treeNZBCreatorResults, FALSE);
214
    gtk_widget_set_sensitive(btnNZBCreatorPerformSearch, FALSE);
215
    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, FALSE);
216
    gtk_widget_set_sensitive(btnNZBCreatorNewerResults, FALSE);
217
    gtk_widget_set_sensitive(btnNZBCreatorOlderResults, FALSE);
218
    gtk_widget_set_sensitive(btnNZBCreatorSelectAll, FALSE);
219
    gtk_widget_set_sensitive(btnNZBCreatorSelectNone, FALSE);
220

                
221
    /* Clear any old results */
222
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeNZBCreatorResults));
223
    gtk_tree_store_clear(GTK_TREE_STORE(model));
224

                
225
    g_return_if_fail(g_thread_create(perform_search_func, &cached_search_opts, FALSE, NULL));
226
}
227

                
228
struct _nzbcreator_data
229
{
230
    time_t oldest_stamp;
231
    time_t newest_stamp;
232
    NGList *file_ids;
233
    char *collection_name;
234
    char *nzbdata;
235
    char *errmsg;
236
};
237

                
238
static gboolean
239
process_nzbcreator_results(gpointer user_data)
240
{
241
    struct _nzbcreator_data *data = (struct _nzbcreator_data*) user_data;
242
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
243
    GtkWidget *btnNZBCreatorPerformSearch = nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch");
244
    GtkWidget *btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
245
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
246
    GtkWidget *expanderNZBCreator = nntpgrab_gui_base_get_widget("expanderNZBCreator");
247
    GtkWidget *btnNZBCreatorNewerResults = nntpgrab_gui_base_get_widget("btnNZBCreatorNewerResults");
248
    GtkWidget *btnNZBCreatorOlderResults = nntpgrab_gui_base_get_widget("btnNZBCreatorOlderResults");
249
    GtkWidget *btnNZBCreatorSelectAll = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectAll");
250
    GtkWidget *btnNZBCreatorSelectNone = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectNone");
251

                
252
    if (!data->nzbdata) {
253
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
254
        nntpgrab_gui_base_dialog_show(windowMain, data->errmsg, GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
255
        g_free(data->errmsg);
256

                
257
        goto out;
258
    }
259

                
260
    nzb_perform_quick_import(data->collection_name, data->nzbdata);
261

                
262
out:
263
    gtk_widget_set_sensitive(treeNZBCreatorResults, TRUE);
264
    gtk_widget_set_sensitive(btnNZBCreatorPerformSearch, TRUE);
265
    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, TRUE);
266
    gtk_widget_set_sensitive(entryNZBCreatorQuery, TRUE);
267
    gtk_widget_set_sensitive(expanderNZBCreator, TRUE);
268
    gtk_widget_set_sensitive(btnNZBCreatorNewerResults, TRUE);
269
    gtk_widget_set_sensitive(btnNZBCreatorOlderResults, TRUE);
270
    gtk_widget_set_sensitive(btnNZBCreatorSelectAll, TRUE);
271
    gtk_widget_set_sensitive(btnNZBCreatorSelectNone, TRUE);
272

                
273
    g_free(data->nzbdata);
274
    g_free(data->collection_name);
275
    ng_list_free(data->file_ids);
276
    g_slice_free(struct _nzbcreator_data, data);
277

                
278
    return FALSE;
279
}
280

                
281
static gpointer
282
retrieve_nzbcreator_results(gpointer user_data)
283
{
284
    struct _nzbcreator_data *data = (struct _nzbcreator_data*) user_data;
285

                
286
    data->nzbdata = nntpgrab_utils_nzbcreator_generate_NZB(data->file_ids, data->oldest_stamp, data->newest_stamp, &data->errmsg);
287

                
288
    g_idle_add(process_nzbcreator_results, data);
289

                
290
    return NULL;
291
}
292

                
293
static gboolean
294
process_newsgroups_list(gpointer data)
295
{
296
    NGList *newsgroups = (NGList*) data;
297
    NGList *list;
298
    GtkWidget *comboNZBCreatorNewsgroups;
299
    GtkWidget *vboxNZBCreatorTab;
300
    GtkListStore *store;
301
    GtkTreeIter iter;
302
    GtkCellRenderer *renderer;
303

                
304
    comboNZBCreatorNewsgroups = nntpgrab_gui_base_get_widget("comboNZBCreatorNewsgroups");
305
    vboxNZBCreatorTab = nntpgrab_gui_base_get_widget("vboxNZBCreatorTab");
306

                
307
    store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
308

                
309
    gtk_list_store_append(store, &iter);
310
    gtk_list_store_set(store, &iter, 0, _("All popular newsgroups"), -1);
311

                
312
    list = newsgroups;
313
    while (list) {
314
        NZBCreatorGroup *group = (NZBCreatorGroup*) list->data;
315

                
316
        gtk_list_store_append(store, &iter);
317
        gtk_list_store_set(store, &iter, 0, group->newsgroup, 1, group->group_id, -1);
318

                
319
        list = ng_list_next(list);
320
    }
321

                
322
    gtk_combo_box_set_model(GTK_COMBO_BOX(comboNZBCreatorNewsgroups), GTK_TREE_MODEL(store));
323
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorNewsgroups), 0);
324

                
325
    renderer = gtk_cell_renderer_text_new ();
326
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comboNZBCreatorNewsgroups), renderer, TRUE);
327
    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comboNZBCreatorNewsgroups), renderer, "text", 0, NULL);
328

                
329
    gtk_widget_set_sensitive(vboxNZBCreatorTab, TRUE);
330

                
331
    nntpgrab_utils_nzbcreator_free_groups(newsgroups);
332

                
333
    return FALSE;
334
}
335

                
336
static gboolean
337
disable_online_search(gpointer data)
338
{
339
    GtkTreeIter iter;
340
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
341
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeNZBCreatorResults));
342

                
343
    g_return_val_if_fail(data != NULL, FALSE);
344

                
345
    gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
346
    gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
347
                            FIELD_SUBJECT, data,
348
                            -1);
349

                
350
    g_free(data);
351

                
352
    return FALSE;
353
}
354

                
355
static gpointer
356
fetch_newsgroups_func(gpointer data)
357
{
358
    NGList *newsgroups;
359
    gboolean api_okay = FALSE;
360
    char *errmsg = NULL;
361

                
362
    if (!nntpgrab_utils_nzbcreator_check_api_version(&api_okay, &errmsg)) {
363
        /* Some error occured while checking the API version */
364
        g_idle_add(disable_online_search, g_strdup_printf(_("Unexpected error occured while connecting to the Online Search:\n%s"), errmsg));
365
        g_free(errmsg);
366
        return NULL;
367
    }
368

                
369
    if (!api_okay) {
370
        /* A newer version of NNTPGrab is required */
371
        g_idle_add(disable_online_search, g_strdup(_("A newer version of NNTPGrab is required to use the Online Search")));
372
        return NULL;
373
    }
374

                
375
    newsgroups = nntpgrab_utils_nzbcreator_get_all_groups(&errmsg);
376
    if (newsgroups) {
377
        g_idle_add(process_newsgroups_list, newsgroups);
378
    } else {
379
        char *msg = g_strdup_printf(_("Error while fetching list of newsgroups from the Online Search service:\n%s"), errmsg);
380
        g_idle_add(process_error, msg);
381
        g_free(errmsg);
382
    }
383

                
384
    return NULL;
385
}
386

                
387
struct _details_data {
388
    GtkTreeStore *store;
389
    GtkTreeIter iter_parent;
390
    ngint64 collection_id;
391
    time_t stamp;
392

                
393
    char *errmsg;
394

                
395
    NGList *result;
396
};
397

                
398
static void
399
on_row_expanded(GtkTreeView *tree_view, GtkTreeIter *iter_parent, GtkTreePath *path, gpointer data)
400
{
401
    GtkTreeIter iter;
402
    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
403
    struct _details_data *details_data = g_slice_new0(struct _details_data);
404
    char *subject = NULL;
405

                
406
    if (!gtk_tree_model_iter_children(model, &iter, iter_parent)) {
407
        /* This is a single-file collection, no need to do anything with it */
408
        return;
409
    }
410

                
411
    gtk_tree_model_get(model, iter_parent, FIELD_COLLECTION_ID, &details_data->collection_id, FIELD_STAMP, &details_data->stamp, -1);
412
    gtk_tree_model_get(model, &iter, FIELD_SUBJECT, &subject, -1);
413

                
414
    if (subject && !strcmp(subject, "unknown")) {
415
        /* No information retrieved yet for this collection, retrieve it right now */
416
        gtk_tree_store_set(GTK_TREE_STORE(model), &iter, FIELD_SUBJECT, _("No information available yet. Please wait a moment..."), -1);
417

                
418
        g_return_if_fail(pool_details != NULL);
419

                
420
        details_data->store = GTK_TREE_STORE(model);
421
        details_data->iter_parent = *iter_parent;
422
        g_thread_pool_push(pool_details, details_data, NULL);
423
    }
424
}
425

                
426
static void
427
on_column_select_toggled(GtkWidget *caller, char *path, gpointer data)
428
{
429
    GtkTreeModel *model = GTK_TREE_MODEL(data);
430
    GtkTreeIter iter;
431
    GtkTreeIter parent;
432
    gboolean val;
433
    GtkWidget *btnNZBCreatorImportFiles;
434
    gboolean selected;
435

                
436
    gtk_tree_model_get_iter_from_string(model, &iter, path);
437

                
438
    gtk_tree_model_get(model, &iter, FIELD_SELECTED, &val, -1);
439
    if (val) {
440
        val = FALSE;
441
    } else {
442
        val = TRUE;
443
    }
444

                
445
    // Has the user clicked on the checkbox of a collection or just a single file?
446
    if (gtk_tree_model_iter_parent(model, &parent, &iter)) {
447
        // Single file
448
        gtk_tree_store_set(GTK_TREE_STORE(model), &iter, FIELD_SELECTED, val, -1);
449

                
450
        /* Some collections only contain one file (thus no expander). Such rows can be ignored */
451
        if (gtk_tree_model_iter_children(model, &iter, &parent)) {
452
            do {
453
                gtk_tree_model_get(model, &iter, FIELD_SELECTED, &selected, -1);
454
                if(selected) {
455
                    //There are items selected
456
                    break;
457
                }
458
            } while (gtk_tree_model_iter_next(model, &iter));
459
            if(!selected) {
460
                //No items selected in this collection
461
                gtk_tree_store_set(GTK_TREE_STORE(model), &parent, FIELD_SELECTED, val, -1);
462
            }
463
        }
464
    } else {
465
        // Whole collection
466
        parent = iter;
467

                
468
        gtk_tree_store_set(GTK_TREE_STORE(model), &parent, FIELD_SELECTED, val, -1);
469

                
470
        /* Some collections only contain one file (thus no expander). Such rows can be ignored */
471
        if (gtk_tree_model_iter_children(model, &iter, &parent)) {
472
            do {
473
                gtk_tree_store_set(GTK_TREE_STORE(model), &iter, FIELD_SELECTED, val, -1);
474
            } while (gtk_tree_model_iter_next(model, &iter));
475
        }
476

                
477
        /* Retrieve the collection details if the collection wasn't expanded earlier yet */
478
        if (val) {
479
            on_row_expanded(GTK_TREE_VIEW(nntpgrab_gui_base_get_widget("treeNZBCreatorResults")), &parent, NULL, NULL);
480
        }
481
    }
482

                
483
    // Is at least one item selected?
484
    g_return_if_fail(gtk_tree_model_get_iter_first(model, &parent));
485

                
486
    do {
487
        gtk_tree_model_get(model, &parent, FIELD_SELECTED, &val, -1);
488
        if (val) {
489
            btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
490
            gtk_widget_set_sensitive(btnNZBCreatorImportFiles, TRUE);
491
            return;
492
        }
493

                
494
        if (gtk_tree_model_iter_children(model, &iter, &parent)) {
495
            do {
496
                gtk_tree_model_get(model, &iter, FIELD_SELECTED, &val, -1);
497
                if (val) {
498
                    btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
499
                    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, TRUE);
500
                    return;
501
                }
502
            } while (gtk_tree_model_iter_next(model, &iter));
503
        }
504
    } while (gtk_tree_model_iter_next(model, &parent));
505

                
506
    btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
507
    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, FALSE);
508
}
509

                
510
static gboolean
511
process_collection_details(gpointer data)
512
{
513
    NGList *list;
514
    char filesize[64];
515
    char stamp[64];
516
    char *newsgroup;
517
    GtkTreeIter iter;
518
    gboolean selected = FALSE;
519
    struct _details_data *details_data = (struct _details_data *) data;
520

                
521
    g_return_val_if_fail(details_data != NULL, FALSE);
522

                
523
    if (details_data->errmsg != NULL) {
524
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
525

                
526
        nntpgrab_gui_base_dialog_show(windowMain, details_data->errmsg, GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
527

                
528
        g_free(details_data->errmsg);
529
        goto out;
530
    }
531

                
532
    gtk_tree_model_get(GTK_TREE_MODEL(details_data->store), &details_data->iter_parent, FIELD_NEWSGROUP, &newsgroup, FIELD_SELECTED, &selected, -1);
533

                
534
    list = details_data->result;
535
    while (list) {
536
        NZBCreatorFile *file = (NZBCreatorFile*) list->data;
537

                
538
        memset(&filesize, 0, sizeof(filesize));
539
        nntpgrab_utils_calculate_file_size(file->file_size, filesize, sizeof(filesize) - 1);
540

                
541
        memset(&stamp, 0, sizeof(stamp));
542
        generate_stamp(file->stamp, stamp, sizeof(stamp) - 1);
543

                
544
        gtk_tree_store_append(details_data->store, &iter, &details_data->iter_parent);
545
        gtk_tree_store_set(details_data->store, &iter,
546
                                FIELD_SUBJECT, file->subject,
547
                                FIELD_POSTER, file->poster,
548
                                FIELD_NEWSGROUP, newsgroup,
549
                                FIELD_FILE_ID, file->file_id,
550
                                FIELD_FILESIZE_STR, filesize,
551
                                FIELD_STAMP, file->stamp,
552
                                FIELD_STAMP_STR, stamp,
553
                                FIELD_COMPLETE_PERCENTAGE, file->complete_percentage,
554
                                FIELD_SELECTED, selected,
555
                                -1);
556

                
557
        list = ng_list_next(list);
558
    }
559

                
560
    /* Remove the placeholder */
561
    g_return_val_if_fail(gtk_tree_model_iter_children(GTK_TREE_MODEL(details_data->store), &iter, &details_data->iter_parent), FALSE);
562
    gtk_tree_store_remove(details_data->store, &iter);
563

                
564
    g_free(newsgroup);
565

                
566
out:
567
    g_slice_free(struct _details_data, details_data);
568

                
569
    return FALSE;
570
}
571

                
572
static void
573
get_collection_details_thread(gpointer data, gpointer user_data)
574
{
575
    struct _details_data *details_data = (struct _details_data *) data;
576

                
577
    g_return_if_fail(details_data != NULL);
578

                
579
    details_data->result = nntpgrab_utils_nzbcreator_retrieve_collection_details(details_data->collection_id, details_data->stamp, &details_data->errmsg);
580

                
581
    /* Process the results back in the main thread */
582
    g_idle_add(process_collection_details, details_data);
583
}
584

                
585
static void
586
select_files_func(gboolean select_all)
587
{
588
    GtkWidget *btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
589
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
590
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeNZBCreatorResults));
591
    GtkTreeIter iter;
592
    GtkTreeIter parent;
593
    gboolean has_children;
594

                
595
    g_return_if_fail(gtk_tree_model_get_iter_first(model, &parent));
596

                
597
    do {
598
        gtk_tree_store_set(GTK_TREE_STORE(model), &parent, FIELD_SELECTED, select_all, -1);
599

                
600
        /* Some items don't have an expander */
601
        if (!(gtk_tree_model_iter_children(model, &iter, &parent))) {
602
            has_children = FALSE;
603
            iter = parent;
604
        } else {
605
            has_children = TRUE;
606
        }
607

                
608
        do {
609
            /* Retrieve collection details if necessary */
610
            if (select_all) {
611
                char *subject = NULL;
612
                gtk_tree_model_get(model, &iter, FIELD_SUBJECT, &subject, -1);
613

                
614
                if (subject && !strcmp(subject, "unknown")) {
615
                    /* This is a placeholder, automatically try to retrieve additional details */
616
                    on_row_expanded(GTK_TREE_VIEW(treeNZBCreatorResults), &parent, NULL, NULL);
617
                }
618

                
619
                g_free(subject);
620
            }
621

                
622
            gtk_tree_store_set(GTK_TREE_STORE(model), &iter, FIELD_SELECTED, select_all, -1);
623

                
624
            if (!has_children) {
625
                break;
626
            }
627
        } while (gtk_tree_model_iter_next(model, &iter));
628
    } while (gtk_tree_model_iter_next(model, &parent));
629

                
630
    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, select_all);
631
}
632

                
633
#endif
634

                
635
G_MODULE_EXPORT void
636
on_btnNZBCreatorPerformSearch_clicked(GtkWidget *caller, gpointer data)
637
{
638
#ifdef HAVE_SOUP
639
    NZBCreatorSearchOpts opts;
640
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
641
    GtkWidget *radNZBCreatorSubjects = nntpgrab_gui_base_get_widget("radNZBCreatorSubjects");
642
    GtkWidget *radNZBCreatorFiles = nntpgrab_gui_base_get_widget("radNZBCreatorFiles");
643
    GtkWidget *radNZBCreatorPosters = nntpgrab_gui_base_get_widget("radNZBCreatorPosters");
644
    GtkWidget *comboNZBCreatorMaxAge = nntpgrab_gui_base_get_widget("comboNZBCreatorMaxAge");
645
    GtkWidget *spinNZBCreatorMinFileSize = nntpgrab_gui_base_get_widget("spinNZBCreatorMinFileSize");
646
    GtkWidget *spinNZBCreatorMaxFileSize = nntpgrab_gui_base_get_widget("spinNZBCreatorMaxFileSize");
647
    GtkWidget *comboNZBCreatorMinFileSize = nntpgrab_gui_base_get_widget("comboNZBCreatorMinFileSize");
648
    GtkWidget *comboNZBCreatorMaxFileSize = nntpgrab_gui_base_get_widget("comboNZBCreatorMaxFileSize");
649
    GtkWidget *comboNZBCreatorPercentage = nntpgrab_gui_base_get_widget("comboNZBCreatorPercentage");
650
    GtkWidget *comboNZBCreatorFileType = nntpgrab_gui_base_get_widget("comboNZBCreatorFileType");
651
    GtkWidget *comboNZBCreatorNewsgroups = nntpgrab_gui_base_get_widget("comboNZBCreatorNewsgroups");
652
    const char *query;
653
    int factor;
654

                
655
    // Query
656
    query = gtk_entry_get_text(GTK_ENTRY(entryNZBCreatorQuery));
657
    if (!query || strlen(query) == 0) {
658
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
659
        nntpgrab_gui_base_dialog_show(windowMain, _("Please enter a search query first"), GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
660
        return;
661
    }
662

                
663
    memset(&opts, 0, sizeof(NZBCreatorSearchOpts));
664
    strncpy(opts.query, query, sizeof(opts.query) - 1);
665

                
666
    // Search only in
667
    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radNZBCreatorSubjects))) {
668
        opts.search_only_in = NZBCREATOR_SEARCH_ONLY_IN_SUBJECTS;
669
    } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radNZBCreatorFiles))) {
670
        opts.search_only_in = NZBCREATOR_SEARCH_ONLY_IN_FILENAMES;
671
    } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radNZBCreatorPosters))) {
672
        opts.search_only_in = NZBCREATOR_SEARCH_ONLY_IN_POSTERS;
673
    } else {
674
        g_critical("Unknown search_only_in option\n");
675
        return;
676
    }
677

                
678
    // Maximum age
679
    switch(gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorMaxAge))) {
680
        case 0:                 // 7 days
681
            opts.max_age = 7;
682
            break;
683

                
684
        case 1:                 // 14 days
685
            opts.max_age = 14;
686
            break;
687

                
688
        case 2:                 // 21 days
689
            opts.max_age = 21;
690
            break;
691

                
692
        case 3:                 // 50 days
693
            opts.max_age = 50;
694
            break;
695

                
696
        case 4:                 // 75 days
697
            opts.max_age = 75;
698
            break;
699

                
700
        case 5:                 // 100 days
701
            opts.max_age = 100;
702
            break;
703

                
704
        case 6:                 // 125 days
705
            opts.max_age = 125;
706
            break;
707

                
708
        case 7:                 // 150 days
709
            opts.max_age = 150;
710
            break;
711

                
712
        default:
713
            g_critical("Unknown max_age option\n");
714
            return;
715
    }
716

                
717
    // Minimal file size
718
    switch(gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorMinFileSize))) {
719
        case 0:
720
            factor = 1024;
721
            break;
722

                
723
        case 1:
724
            factor = 1024 * 1024;
725
            break;
726

                
727
        case 2:
728
            factor = 1024 * 1024 * 1024;
729
            break;
730

                
731
        default:
732
            g_critical("Unknown min_file_size option\n");
733
            return;
734
    }
735

                
736
    opts.minimal_file_size = (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinNZBCreatorMinFileSize));
737
    if (opts.minimal_file_size > 0) {
738
        opts.minimal_file_size *= factor;
739
    }
740

                
741
    // Maximal file size
742
    switch(gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorMaxFileSize))) {
743
        case 0:
744
            factor = 1024;
745
            break;
746

                
747
        case 1:
748
            factor = 1024 * 1024;
749
            break;
750

                
751
        case 2:
752
            factor = 1024 * 1024 * 1024;
753
            break;
754

                
755
        default:
756
            g_critical("Unknown max_file_size option\n");
757
            return;
758
    }
759

                
760
    opts.maximal_file_size = (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinNZBCreatorMaxFileSize));
761
    if (opts.maximal_file_size > 0) {
762
        opts.maximal_file_size *= factor;
763
    }
764

                
765
    // Percentage complete
766
    switch(gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorPercentage))) {
767
        case 0:                 // Any percentage
768
            opts.percentage_complete = 0;
769
            break;
770

                
771
        case 1:                 // Only complete files (100%)
772
            opts.percentage_complete = 100;
773
            break;
774

                
775
        case 2:                 // More than 95%
776
            opts.percentage_complete = 95;
777
            break;
778

                
779
        case 3:                 // More than 90%
780
            opts.percentage_complete = 90;
781
            break;
782

                
783
        case 4:                 // More than 85%
784
            opts.percentage_complete = 85;
785
            break;
786

                
787
        case 5:                 // More than 80%
788
            opts.percentage_complete = 80;
789
            break;
790

                
791
        case 6:                 // More than 70%
792
            opts.percentage_complete = 70;
793
            break;
794

                
795
        case 7:                 // More than 60%
796
            opts.percentage_complete = 60;
797
            break;
798

                
799
        case 8:                 // More than 50%
800
            opts.percentage_complete = 50;
801
            break;
802

                
803
        default:
804
            g_critical("Unknown percentage option\n");
805
            return;
806
    }
807

                
808
    // File type
809
    switch(gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorFileType))) {
810
        case 0:                 // All file types
811
            opts.file_type = NNTP_FILE_TYPE_UNKNOWN;
812
            break;
813

                
814
        case 1:                 // NZB files
815
            opts.file_type = NNTP_FILE_TYPE_NZB;
816
            break;
817

                
818
        case 2:                 // PAR files
819
            opts.file_type = NNTP_FILE_TYPE_PAR;
820
            break;
821

                
822
        case 3:                 // PAR2 files
823
            opts.file_type = NNTP_FILE_TYPE_PAR2;
824
            break;
825

                
826
        case 4:                 // NFO files
827
            opts.file_type = NNTP_FILE_TYPE_NFO;
828
            break;
829

                
830
        case 5:                 // SFV files
831
            opts.file_type = NNTP_FILE_TYPE_SFV;
832
            break;
833

                
834
        case 6:                 // RAR files
835
            opts.file_type = NNTP_FILE_TYPE_RAR;
836
            break;
837

                
838
        default:
839
            g_critical("Unknown file_type option\n");
840
            return;
841
    }
842

                
843
    // Newsgroup
844
    if (gtk_combo_box_get_active(GTK_COMBO_BOX(comboNZBCreatorNewsgroups)) > 0) {
845
        GtkTreeIter iter;
846
        GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(comboNZBCreatorNewsgroups));
847

                
848
        gtk_combo_box_get_active_iter(GTK_COMBO_BOX(comboNZBCreatorNewsgroups), &iter);
849
        gtk_tree_model_get(model, &iter, 1, &opts.group_to_search, -1);
850
    }
851

                
852
    /* Search result offset */
853
    opts.offset = 0;
854

                
855
    /* Keep the search query cached so we can re-use it later */
856
    memcpy(&cached_search_opts, &opts, sizeof(NZBCreatorSearchOpts));
857

                
858
    perform_search();
859
#endif
860
}
861

                
862
G_MODULE_EXPORT void
863
on_btnNZBCreatorImportFiles_clicked(GtkWidget *caller, gpointer user_data)
864
{
865
#ifdef HAVE_SOUP
866
    GtkWidget *treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
867
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeNZBCreatorResults));
868
    GtkWidget *btnNZBCreatorPerformSearch = nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch");
869
    GtkWidget *btnNZBCreatorImportFiles = nntpgrab_gui_base_get_widget("btnNZBCreatorImportFiles");
870
    GtkWidget *entryNZBCreatorQuery = nntpgrab_gui_base_get_widget("entryNZBCreatorQuery");
871
    GtkWidget *expanderNZBCreator = nntpgrab_gui_base_get_widget("expanderNZBCreator");
872
    GtkWidget *btnNZBCreatorNewerResults = nntpgrab_gui_base_get_widget("btnNZBCreatorNewerResults");
873
    GtkWidget *btnNZBCreatorOlderResults = nntpgrab_gui_base_get_widget("btnNZBCreatorOlderResults");
874
    GtkWidget *btnNZBCreatorSelectAll = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectAll");
875
    GtkWidget *btnNZBCreatorSelectNone = nntpgrab_gui_base_get_widget("btnNZBCreatorSelectNone");
876
    GtkTreeIter iter;
877
    GtkTreeIter parent;
878
    struct _nzbcreator_data *data;
879
    gboolean val;
880
    int stamp;
881
    char *collection_name_current = NULL;
882
    gboolean has_children;
883
    const char *query = gtk_entry_get_text(GTK_ENTRY(entryNZBCreatorQuery));
884

                
885
    g_return_if_fail(gtk_tree_model_get_iter_first(model, &parent));
886

                
887
    gtk_widget_set_sensitive(treeNZBCreatorResults, FALSE);
888
    gtk_widget_set_sensitive(btnNZBCreatorPerformSearch, FALSE);
889
    gtk_widget_set_sensitive(btnNZBCreatorImportFiles, FALSE);
890
    gtk_widget_set_sensitive(entryNZBCreatorQuery, FALSE);
891
    gtk_widget_set_sensitive(expanderNZBCreator, FALSE);
892
    gtk_widget_set_sensitive(btnNZBCreatorNewerResults, FALSE);
893
    gtk_widget_set_sensitive(btnNZBCreatorOlderResults, FALSE);
894
    gtk_widget_set_sensitive(btnNZBCreatorSelectAll, FALSE);
895
    gtk_widget_set_sensitive(btnNZBCreatorSelectNone, FALSE);
896

                
897
    data = g_slice_new0(struct _nzbcreator_data);
898

                
899
    do {
900
        gtk_tree_model_get(model, &parent, FIELD_SHORT_COLLECTION_NAME, &collection_name_current, -1);
901

                
902
        /* Some items don't have an expander */
903
        if (!(gtk_tree_model_iter_children(model, &iter, &parent))) {
904
            has_children = FALSE;
905
            iter = parent;
906
        } else {
907
            has_children = TRUE;
908
        }
909

                
910
        do {
911
            gint64 file_id = -1;
912

                
913
            gtk_tree_model_get(model, &iter, FIELD_FILE_ID, &file_id, FIELD_SELECTED, &val, FIELD_STAMP, &stamp, -1);
914
            if (val) {
915
                // Use the name of the collection
916
                if (!data->collection_name) {
917
                    data->collection_name = g_strdup(collection_name_current);
918
                } else {
919
                    if (strcmp(data->collection_name, collection_name_current)) {
920
                        // Or use the search query when there are multiple collections involved
921
                        if (strcmp(data->collection_name, query)) {
922
                            g_free(data->collection_name);
923
                            data->collection_name = g_strdup(query);
924
                        }
925
                    }
926
                }
927

                
928
                data->file_ids = ng_list_append(data->file_ids, GINT_TO_POINTER((int)file_id));
929

                
930
                if (stamp > 0 && (data->oldest_stamp == 0 || stamp < data->oldest_stamp)) {
931
                    data->oldest_stamp = stamp;
932
                }
933

                
934
                if (data->newest_stamp == 0 || stamp > data->newest_stamp) {
935
                    data->newest_stamp = stamp;
936
                }
937
            }
938

                
939
            if (!has_children) {
940
                break;
941
            }
942
        } while (gtk_tree_model_iter_next(model, &iter));
943

                
944
        g_free(collection_name_current);
945
    } while (gtk_tree_model_iter_next(model, &parent));
946

                
947
    g_return_if_fail(data->collection_name != NULL);
948

                
949
    /* Perform the retrieval in a seperate thread to avoid a freeze in the GUI */
950
    g_return_if_fail(g_thread_create(retrieve_nzbcreator_results, data, FALSE, NULL));
951
#endif
952
}
953

                
954
G_MODULE_EXPORT void
955
on_entryNZBCreatorQuery_activate(GtkWidget *caller, gpointer data)
956
{
957
#ifdef HAVE_SOUP
958
    gtk_button_clicked(GTK_BUTTON(nntpgrab_gui_base_get_widget("btnNZBCreatorPerformSearch")));
959
#endif
960
}
961

                
962
G_MODULE_EXPORT void
963
on_btnNZBCreatorSelectAll_clicked(GtkWidget *caller, gpointer data)
964
{
965
#ifdef HAVE_SOUP
966
    select_files_func(TRUE);
967
#endif
968
}
969

                
970
G_MODULE_EXPORT void
971
on_btnNZBCreatorSelectNone_clicked(GtkWidget *caller, gpointer data)
972
{
973
#ifdef HAVE_SOUP
974
    select_files_func(FALSE);
975
#endif
976
}
977

                
978
G_MODULE_EXPORT void
979
on_btnNZBCreatorOlderResults_clicked(GtkWidget *caller, gpointer data)
980
{
981
#ifdef HAVE_SOUP
982
    g_return_if_fail(results_per_page > 0);
983
    g_return_if_fail(cached_search_opts.offset >= 0);
984

                
985
    cached_search_opts.offset += results_per_page;
986

                
987
    perform_search();
988
#endif
989
}
990

                
991
G_MODULE_EXPORT void
992
on_btnNZBCreatorNewerResults_clicked(GtkWidget *caller, gpointer data)
993
{
994
#ifdef HAVE_SOUP
995
    g_return_if_fail(results_per_page > 0);
996
    g_return_if_fail(cached_search_opts.offset >= results_per_page);
997

                
998
    cached_search_opts.offset -= results_per_page;
999

                
1000
    perform_search();
1001
#endif
1002
}
1003

                
1004
void
1005
nzbcreator_initialize(void)
1006
{
1007
#ifdef HAVE_SOUP
1008
    GtkWidget *treeNZBCreatorResults;
1009
    GtkWidget *comboNZBCreatorMinFileSize;
1010
    GtkWidget *comboNZBCreatorMaxFileSize;
1011
    GtkWidget *comboNZBCreatorMaxAge;
1012
    GtkWidget *comboNZBCreatorPercentage;
1013
    GtkWidget *comboNZBCreatorFileType;
1014

                
1015
    GtkTreeStore *store;
1016
    GtkCellRenderer *cellRenderer;
1017

                
1018
    treeNZBCreatorResults = nntpgrab_gui_base_get_widget("treeNZBCreatorResults");
1019
    comboNZBCreatorMinFileSize = nntpgrab_gui_base_get_widget("comboNZBCreatorMinFileSize");
1020
    comboNZBCreatorMaxFileSize = nntpgrab_gui_base_get_widget("comboNZBCreatorMaxFileSize");
1021
    comboNZBCreatorMaxAge = nntpgrab_gui_base_get_widget("comboNZBCreatorMaxAge");
1022
    comboNZBCreatorPercentage = nntpgrab_gui_base_get_widget("comboNZBCreatorPercentage");
1023
    comboNZBCreatorFileType = nntpgrab_gui_base_get_widget("comboNZBCreatorFileType");
1024

                
1025
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorMinFileSize), 1);
1026
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorMaxFileSize), 1);
1027
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorMaxAge), 2);
1028
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorPercentage), 0);
1029
    gtk_combo_box_set_active(GTK_COMBO_BOX(comboNZBCreatorFileType), 0);
1030

                
1031
    store = gtk_tree_store_new( LAST_FIELD,
1032
                                G_TYPE_INT64    /* FIELD_COLLECTION_ID */,
1033
                                G_TYPE_STRING   /* FIELD_COLLECTION_NAME */,
1034
                                G_TYPE_STRING   /* FIELD_SHORT_COLLECTION_NAME */,
1035
                                G_TYPE_STRING   /* FIELD_SUBJECT */,
1036
                                G_TYPE_STRING   /* FIELD_POSTER */,
1037
                                G_TYPE_STRING   /* FIELD_NEWSGROUP */,
1038
                                G_TYPE_INT64    /* FIELD_FILE_ID */,
1039
                                G_TYPE_STRING   /* FIELD_FILESIZE_STR */,
1040
                                G_TYPE_INT      /* FIELD_STAMP */,
1041
                                G_TYPE_STRING   /* FIELD_STAMP_STR */,
1042
                                G_TYPE_INT      /* FIELD_COMPLETE_PERCENTAGE */,
1043
                                G_TYPE_BOOLEAN  /* FIELD_SELECTED */);
1044

                
1045
    cellRenderer = gtk_cell_renderer_toggle_new();
1046
    columns[FIELD_SELECTED] = gtk_tree_view_column_new_with_attributes("", cellRenderer, "active", FIELD_SELECTED, NULL);
1047
    gtk_tree_view_column_set_resizable(columns[FIELD_SELECTED], TRUE);
1048
    gtk_tree_view_column_set_min_width(columns[FIELD_SELECTED], 30);
1049
    gtk_tree_view_column_set_reorderable(columns[FIELD_SELECTED], TRUE);
1050
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_SELECTED], -1);
1051
    g_signal_connect(GTK_CELL_RENDERER_TOGGLE(cellRenderer), "toggled", G_CALLBACK(on_column_select_toggled), store);
1052

                
1053
    cellRenderer = gtk_cell_renderer_progress_new();
1054
    columns[FIELD_COMPLETE_PERCENTAGE] = gtk_tree_view_column_new_with_attributes(_("% complete"), cellRenderer, "value", FIELD_COMPLETE_PERCENTAGE, NULL);
1055
    gtk_tree_view_column_set_resizable(columns[FIELD_COMPLETE_PERCENTAGE], TRUE);
1056
    gtk_tree_view_column_set_reorderable(columns[FIELD_COMPLETE_PERCENTAGE], TRUE);
1057
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_COMPLETE_PERCENTAGE], -1);
1058

                
1059
    cellRenderer = gtk_cell_renderer_text_new();
1060
    columns[FIELD_SUBJECT] = gtk_tree_view_column_new_with_attributes(_("Subject"), cellRenderer, "text", FIELD_SUBJECT, NULL);
1061
    gtk_tree_view_column_set_resizable(columns[FIELD_SUBJECT], TRUE);
1062
    gtk_tree_view_column_set_reorderable(columns[FIELD_SUBJECT], TRUE);
1063
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_SUBJECT], -1);
1064

                
1065
    cellRenderer = gtk_cell_renderer_text_new();
1066
    columns[FIELD_POSTER] = gtk_tree_view_column_new_with_attributes(_("Poster"), cellRenderer, "text", FIELD_POSTER, NULL);
1067
    gtk_tree_view_column_set_resizable(columns[FIELD_POSTER], TRUE);
1068
    gtk_tree_view_column_set_reorderable(columns[FIELD_POSTER], TRUE);
1069
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_POSTER], -1);
1070

                
1071
    cellRenderer = gtk_cell_renderer_text_new();
1072
    columns[FIELD_NEWSGROUP] = gtk_tree_view_column_new_with_attributes(_("Newsgroup"), cellRenderer, "text", FIELD_NEWSGROUP, NULL);
1073
    gtk_tree_view_column_set_resizable(columns[FIELD_NEWSGROUP], TRUE);
1074
    gtk_tree_view_column_set_reorderable(columns[FIELD_NEWSGROUP], TRUE);
1075
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_NEWSGROUP], -1);
1076

                
1077
    cellRenderer = gtk_cell_renderer_text_new();
1078
    columns[FIELD_FILESIZE_STR] = gtk_tree_view_column_new_with_attributes(_("File size"), cellRenderer, "text", FIELD_FILESIZE_STR, NULL);
1079
    gtk_tree_view_column_set_resizable(columns[FIELD_FILESIZE_STR], TRUE);
1080
    gtk_tree_view_column_set_reorderable(columns[FIELD_FILESIZE_STR], TRUE);
1081
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_FILESIZE_STR], -1);
1082

                
1083
    cellRenderer = gtk_cell_renderer_text_new();
1084
    columns[FIELD_STAMP_STR] = gtk_tree_view_column_new_with_attributes(_("Stamp"), cellRenderer, "text", FIELD_STAMP_STR, NULL);
1085
    gtk_tree_view_column_set_resizable(columns[FIELD_STAMP_STR], TRUE);
1086
    gtk_tree_view_column_set_reorderable(columns[FIELD_STAMP_STR], TRUE);
1087
    gtk_tree_view_insert_column(GTK_TREE_VIEW(treeNZBCreatorResults), columns[FIELD_STAMP_STR], -1);
1088

                
1089
    gtk_tree_view_set_model(GTK_TREE_VIEW(treeNZBCreatorResults), GTK_TREE_MODEL(store));
1090

                
1091
    // Retrieve the list of available newsgroups in a seperate thread
1092
    g_return_if_fail(g_thread_create(fetch_newsgroups_func, NULL, FALSE, NULL));
1093

                
1094
    g_signal_connect(treeNZBCreatorResults, "row-expanded", G_CALLBACK(on_row_expanded), NULL);
1095

                
1096
    pool_details = g_thread_pool_new(get_collection_details_thread, NULL, 5, FALSE, NULL);
1097

                
1098
    results_per_page = 0;
1099
    memset(&cached_search_opts, 0, sizeof(cached_search_opts));
1100
#else
1101
    GtkWidget *vboxNZBCreatorTab = nntpgrab_gui_base_get_widget("vboxNZBCreatorTab");
1102
    gtk_widget_hide(vboxNZBCreatorTab);
1103
#endif
1104
}