Revision 1833

trunk/tests/test_nzbcreator.c (revision 1833)
95 95
    NGList *list;
96 96
    NGList *files;
97 97

                
98
    if (!(files = nntpgrab_utils_nzbcreator_retrieve_collection_details(64752781, &errmsg))) {
98
    if (!(files = nntpgrab_utils_nzbcreator_retrieve_collection_details(106946812, 1307919905, &errmsg))) {
99 99
        g_error("%s", errmsg);
100 100
    }
101 101

                
trunk/base/nntpgrab_utils.h (revision 1833)
293 293
    int complete_percentage;
294 294
    int num_regular_files;
295 295
    int num_par2_files;
296
    ngint64 first_file_id;
296 297
} NZBCreatorCollection;
297 298

                
298 299
/**
... ...
559 560
 */
560 561
void                     nntpgrab_utils_nzbcreator_free_result(NZBCreatorSearchResult *result);
561 562

                
562
NGList *nntpgrab_utils_nzbcreator_retrieve_collection_details(ngint64 collection_id, char **errmsg);
563
/**
564
 * nntpgrab_utils_nzbcreator_retrieve_collection_details:
565
 * @collection_id:                          The id of the collection whose details need to be retrieved
566
 * @stamp:                                  The stamp belonging to the collection id
567
 * @errmsg:         (allow-none) (out):     Pointer to a char*. If an errors occurs, the reason will be placed in this field. Needs to be freed using ngfree(). Can be NULL to ignore errors
568
 *
569
 * Retrieve a list of files belonging to a collection
570
 *
571
 * Returns:                                 A list containing NZBCreatorFile's. Needs to be free'd using nntpgrab_utils_nzbcreator_free_collection_details(). If an error occurs, the value NULL will be returned and errmsg will be set
572
 */
573
NGList *nntpgrab_utils_nzbcreator_retrieve_collection_details(ngint64 collection_id, time_t stamp, char **errmsg);
563 574

                
575
/**
576
 * nntpgrab_utils_nzbcreator_free_collection_details: (skip)
577
 * @files:          The list of files as returned by nntpgrab_utils_nzbcreator_retrieve_collection_details()
578
 *
579
 * Free the list with collection details
580
 */
564 581
void nntpgrab_utils_nzbcreator_free_collection_details(NGList *files);
565 582

                
566 583
/**
trunk/base/nzbcreator.c (revision 1833)
94 94
    g_object_unref(msg);
95 95
    g_object_unref(session);
96 96

                
97
    if (result == 20110409) {
97
    if (result == 20110613) {
98 98
        *api_okay = TRUE;
99 99
    } else {
100 100
        *api_okay = FALSE;
... ...
354 354
        int complete_percentage = 0;
355 355
        int num_regular_files = 0;
356 356
        int num_par2_files = 0;
357
        int first_file_id = -1;
357 358

                
358 359
        if (!soup_value_array_get_nth(matches, i, G_TYPE_HASH_TABLE, &hash_collection)) {
359 360
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
... ...
372 373
                                                            "complete_percentage", G_TYPE_INT, &complete_percentage,
373 374
                                                            "num_regular_files", G_TYPE_INT, &num_regular_files,
374 375
                                                            "num_par2_files", G_TYPE_INT, &num_par2_files,
376
                                                            "first_file_id", G_TYPE_INT, &first_file_id,
375 377
                                                            NULL)) {
376 378
            g_warning(__FILE__ ":%i Unable to parse values", __LINE__);
377 379
            g_hash_table_destroy(hash_collection);
... ...
391 393
        collection->complete_percentage = complete_percentage;
392 394
        collection->num_regular_files = num_regular_files;
393 395
        collection->num_par2_files = num_par2_files;
396
        collection->first_file_id = first_file_id;
394 397

                
395 398
        result->collections = ng_list_append(result->collections, collection);
396 399
    }
... ...
404 407
}
405 408

                
406 409
NGList *
407
nntpgrab_utils_nzbcreator_retrieve_collection_details(ngint64 collection_id, char **errmsg)
410
nntpgrab_utils_nzbcreator_retrieve_collection_details(ngint64 collection_id, time_t stamp, char **errmsg)
408 411
{
409 412
    NGList *result = NULL;
410 413

                
... ...
432 435

                
433 436
#ifdef HAVE_SOUP_GZIP
434 437
    /* Enable gzip compression */
435
    //soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
438
    soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER);
436 439
#endif
437 440

                
438 441
    g_signal_connect (session, "authenticate", G_CALLBACK(authenticate_cb), NULL);
439 442

                
440
    args = soup_value_hash_new_with_vals("collection_id", G_TYPE_INT, (int) collection_id, NULL);
443
    args = soup_value_hash_new_with_vals("collection_id", G_TYPE_INT, (int) collection_id,
444
                                         "stamp", G_TYPE_INT, (int) stamp,
445
                                         NULL);
441 446
    msg = soup_xmlrpc_request_new(URI, "retrieveCollectionDetails", G_TYPE_HASH_TABLE, args, G_TYPE_INVALID);
442 447

                
443 448
    soup_session_send_message(session, msg);
... ...
510 515
        strncpy(file->poster, poster, sizeof(file->poster) - 1);
511 516
        file->num_parts_found = num_parts_found;
512 517
        file->num_parts_expected = num_parts_expected;
513
        file->file_type = file_type;
514
        file->file_size = (NNTPFileType) file_size;
518
        file->file_type = (NNTPFileType) file_type;
519
        file->file_size = file_size;
515 520
        file->stamp = (time_t) stamp;
516 521
        file->complete_percentage = complete_percentage;
517 522

                
trunk/client/gui_qt/WidgetNZBCreator.ui (revision 1833)
98 98
       collection_name_short
99 99
      
100 100
     
101
     
102
      
103
       is_single_file
104
      
105
     
101 106
    
102 107
   
103 108
   
trunk/client/gui_qt/WidgetNZBCreator.cpp (revision 1833)
14 14
    FIELD_FILE_SIZE,
15 15
    FIELD_STAMP,
16 16
    FIELD_FILE_ID,
17
    FIELD_COLLECTION_NAME_SHORT
17
    FIELD_COLLECTION_NAME_SHORT,
18
    FIELD_IS_SINGLE_FILE
18 19
};
19 20

                
20 21
WidgetNZBCreator::WidgetNZBCreator(QNNTPGrabGlue *glue, QWidget *parent) :
... ...
40 41

                
41 42
    ui->treeWidget->setColumnHidden(FIELD_FILE_ID, true);
42 43
    ui->treeWidget->setColumnHidden(FIELD_COLLECTION_NAME_SHORT, true);
44
    ui->treeWidget->setColumnHidden(FIELD_IS_SINGLE_FILE, true);
43 45

                
44 46
    connect(&watcher_search, SIGNAL(finished()), SLOT(performSearch_finished()));
45
    connect(&watcher_details, SIGNAL(finished()), SLOT(performGetDetails_finished()));
46 47
    connect(&watcher_import, SIGNAL(finished()), SLOT(performImport_finished()));
48

                
49
    pool_details.setMaxThreadCount(5);
47 50
}
48 51

                
49 52
WidgetNZBCreator::~WidgetNZBCreator()
... ...
143 146
        collection_item->setText(FIELD_PERCENTAGE_COMPLETE, QString("%1").arg(collection.complete_percentage));
144 147
        collection_item->setText(FIELD_FILE_ID, QString("%1").arg(collection.collection_id));
145 148

                
146
        QTreeWidgetItem *file_item = new QTreeWidgetItem(collection_item);
147
        file_item->setText(FIELD_SUBJECT, tr("No information available yet. Please wait a moment..."));
148

                
149
#if 0
150
        int percentage_total = 0;
151
        QString poster = "";
152
        bool unique_poster = true;
153

                
154 149
        /* Don't show an expander for collections with only one file */
155
        if (collection.files.count() == 1) {
156
            collection_item->setText(FIELD_FILE_ID, QString("%1").arg(collection.files.at(0).file_id));
157
            percentage_total = collection.files.at(0).complete_percentage;
150
        if (collection.first_file_id != -1) {
151
            collection_item->setText(FIELD_FILE_ID, QString("%1").arg(collection.first_file_id));
152
            collection_item->setText(FIELD_IS_SINGLE_FILE, "1");
158 153
        } else {
159
            Q_FOREACH(QNZBCreator::File file, collection.files) {
160
                QTreeWidgetItem *file_item = new QTreeWidgetItem(collection_item);
161

                
162
                file_item->setCheckState(FIELD_IMPORT, Qt::Unchecked);
163
                file_item->setText(FIELD_PERCENTAGE_COMPLETE, QString("%1").arg(file.complete_percentage));
164
                file_item->setText(FIELD_SUBJECT, file.subject);
165
                file_item->setText(FIELD_POSTER, file.poster);
166
                file_item->setText(FIELD_NEWSGROUP, collection.newsgroup);
167
                file_item->setText(FIELD_FILE_SIZE, QNNTPGrabGlue::utilsCalculateFileSize(file.file_size));
168
                file_item->setText(FIELD_STAMP, file.stamp.toString());
169
                file_item->setText(FIELD_FILE_ID, QString("%1").arg(file.file_id));
170
                percentage_total += file.complete_percentage;
171

                
172
                if (poster.isEmpty()) {
173
                    poster = file.poster;
174
                } else if (poster != file.poster) {
175
                    unique_poster = false;
176
                }
177
            }
154
            QTreeWidgetItem *file_item = new QTreeWidgetItem(collection_item);
155
            file_item->setText(FIELD_SUBJECT, "unknown");
178 156
        }
179
#endif
180 157

                
181 158
        ui->treeWidget->addTopLevelItem(collection_item);
182 159
    }
183 160
}
184 161

                
185
WidgetNZBCreator::DetailsResult WidgetNZBCreator::performGetDetails(QTreeWidgetItem *item, qint64 collection_id)
162
void WidgetNZBCreator::performGetDetails(QTreeWidgetItem *item, int collection_id, QDateTime stamp)
186 163
{
187
    WidgetNZBCreator::DetailsResult ret;
164
    WidgetNZBCreatorDetails *watcher = new WidgetNZBCreatorDetails(item, collection_id, stamp);
188 165

                
189
    ret.item = item;
190
    ret.ret = nzbcreator.retrieveAdditionalCollectionDetails(collection_id, ret.errmsg, ret.files);
166
    item->child(0)->setText(FIELD_SUBJECT, tr("No information available yet. Please wait a moment..."));
191 167

                
192
    return ret;
168
    connect(watcher, SIGNAL(finished(bool,QTreeWidgetItem*,QList,QString)), SLOT(performGetDetails_finished(bool,QTreeWidgetItem*,QList,QString)), Qt::QueuedConnection);
169
    pool_details.start(watcher);
193 170
}
194 171

                
195
void WidgetNZBCreator::performGetDetails_finished()
172
void WidgetNZBCreator::performGetDetails_finished(bool ret, QTreeWidgetItem *item, QList files, QString errmsg)
196 173
{
197
    WidgetNZBCreator::DetailsResult result = future_details.result();
198

                
199
    if (!result.ret) {
200
        qWarning((tr("Retrieving online search collection details failed: ") + result.errmsg).toUtf8());
174
    if (!ret) {
175
        qWarning((tr("Retrieving online search collection details failed: ") + errmsg).toUtf8());
201 176
        return;
202 177
    }
203 178

                
204
     Q_FOREACH(QNZBCreator::File file, result.files) {
205
         QTreeWidgetItem *file_item = new QTreeWidgetItem(result.item);
179
     Q_FOREACH(QNZBCreator::File file, files) {
180
         QTreeWidgetItem *file_item = new QTreeWidgetItem(item);
206 181

                
207
         file_item->setCheckState(FIELD_IMPORT, Qt::Unchecked);
182
         /* Automatically select all the files if the placeholder is checked already */
183
         file_item->setCheckState(FIELD_IMPORT, item->checkState(FIELD_IMPORT));
184

                
208 185
         file_item->setText(FIELD_PERCENTAGE_COMPLETE, QString("%1").arg(file.complete_percentage));
209 186
         file_item->setText(FIELD_SUBJECT, file.subject);
210 187
         file_item->setText(FIELD_POSTER, file.poster);
211
         file_item->setText(FIELD_NEWSGROUP, result.item->text(FIELD_NEWSGROUP));
188
         file_item->setText(FIELD_NEWSGROUP, item->text(FIELD_NEWSGROUP));
212 189
         file_item->setText(FIELD_FILE_SIZE, QNNTPGrabGlue::utilsCalculateFileSize(file.file_size));
213 190
         file_item->setText(FIELD_STAMP, file.stamp.toString());
214 191
         file_item->setText(FIELD_FILE_ID, QString("%1").arg(file.file_id));
215 192
     }
216 193

                
217 194
     /* Remove the placeholder item */
218
     result.item->removeChild(result.item->child(0));
195
     item->removeChild(item->child(0));
219 196
}
220 197

                
221 198
void WidgetNZBCreator::btnImport_clicked()
... ...
254 231
                }
255 232
            }
256 233
        }
234

                
235
        /* Is this a single-file collection? */
236
        if (collection_item->text(FIELD_IS_SINGLE_FILE) != "" &&
237
            collection_item->checkState(FIELD_IMPORT) == Qt::Checked) {
238

                
239
            file_ids.append(collection_item->text(FIELD_FILE_ID).toInt());
240

                
241
            if (collection_name.isEmpty()) {
242
                collection_name = collection_item->text(FIELD_COLLECTION_NAME_SHORT);
243
            } else if (collection_name != collection_item->text(FIELD_COLLECTION_NAME_SHORT)) {
244
                multiple_collections = TRUE;
245
            }
246
        }
257 247
    }
258 248

                
259 249
    if (collection_name.isEmpty()) {
... ...
326 316
        return;
327 317
    }
328 318

                
329
    if (item->checkState(column) == Qt::Checked) {
330
        for (int i = 0; i < item->childCount(); i++) {
331
            item->child(i)->setCheckState(FIELD_IMPORT, Qt::Checked);
319
    for (int i = 0; i < item->childCount(); i++) {
320
        QTreeWidgetItem *item_child = item->child(i);
321
        item_child->setCheckState(FIELD_IMPORT, item->checkState(column));
322

                
323
        /* Do we know the contents of this collection yet? */
324
        if (i == 0 && item_child->text(FIELD_SUBJECT) == "unknown") {
325
            /* Start a job to retrieve the details */
326
            qint64 collection_id = item->text(FIELD_FILE_ID).toInt();
327
            QDateTime stamp = QDateTime::fromString(item->text(FIELD_STAMP));
328
            performGetDetails(item, collection_id, stamp);
332 329
        }
333
    } else {
334
        for (int i = 0; i < item->childCount(); i++) {
335
            item->child(i)->setCheckState(FIELD_IMPORT, Qt::Unchecked);
336
        }
337 330
    }
338 331
}
339 332

                
... ...
344 337
    QTreeWidgetItem *item_child = ui->treeWidget->getItemByIndex(idx_child);
345 338
    Q_ASSERT(item_child != NULL);
346 339

                
347
    if (item_child->text(FIELD_SUBJECT) != tr("No information available yet. Please wait a moment...")) {
340
    if (item_child->text(FIELD_SUBJECT) != "unknown") {
348 341
        /* Nothing to do as the real data is already there */
349 342
        return;
350 343
    }
... ...
354 347
    Q_ASSERT(item_parent != NULL);
355 348

                
356 349
    qint64 collection_id = item_parent->text(FIELD_FILE_ID).toInt();
357
    future_details = QtConcurrent::run(this, &WidgetNZBCreator::performGetDetails, item_parent, collection_id);
358
    watcher_details.setFuture(future_details);
350
    QDateTime stamp = QDateTime::fromString(item_parent->text(FIELD_STAMP));
351
    performGetDetails(item_parent, collection_id, stamp);
359 352
}
trunk/client/gui_qt/QNZBCreator.h (revision 1833)
108 108
        int complete_percentage;
109 109
        int num_regular_files;
110 110
        int num_par2_files;
111
        qint64 first_file_id;
111 112
    };
112 113

                
113 114
    /**
... ...
156 157
     */
157 158
    bool performSearch(QNZBCreator::SearchOpts opts, QString &errmsg, QNZBCreator::SearchResult &result);
158 159

                
159
    bool retrieveAdditionalCollectionDetails(qint64 collection_id, QString &errmsg, QList &result);
160
    /**
161
     * retrieveAdditionalCollectionDetails:
162
     * @collection_id:  The id of the collection whose details need to be retrieved
163
     * @stamp:          The stamp belonging to the collection id
164
     * @errmsg:         If an errors occurs, the reason will be placed in this field
165
     * @result:         Location where the list of files belonging to the collection can be saved
166
     *
167
     * Retrieve a list of files belonging to a collection
168
     *
169
     * Returns:         TRUE on success, FALSE on failure (errmsg will be set)
170
     */
171
    bool retrieveAdditionalCollectionDetails(qint64 collection_id, QDateTime stamp, QString &errmsg, QList &result);
160 172

                
161 173
    /**
162 174
     * generateNZB:
trunk/client/gui_qt/gui_qt.pro (revision 1833)
42 42
    DownloadQueueItem.cpp \
43 43
    DownloadQueueSelectionModel.cpp \
44 44
    NGApplication.cpp \
45
    WidgetNZBCreatorTree.cpp
45
    WidgetNZBCreatorTree.cpp \
46
    WidgetNZBCreatorDetails.cpp
46 47
HEADERS += mainwindow.h \
47 48
    QNNTPGrabGlue.h \
48 49
    WidgetConfig.h \
... ...
77 78
    DownloadQueueItem.h \
78 79
    DownloadQueueSelectionModel.h \
79 80
    NGApplication.h \
80
    WidgetNZBCreatorTree.h
81
    WidgetNZBCreatorTree.h \
82
    WidgetNZBCreatorDetails.h
81 83
FORMS += mainwindow.ui \
82 84
    WidgetConfig.ui \
83 85
    WidgetDownloadQueue.ui \
trunk/client/gui_qt/WidgetNZBCreatorDetails.h (revision 1833)
1
#ifndef WIDGETNZBCREATORDETAILS_H
2
#define WIDGETNZBCREATORDETAILS_H
3

                
4
#include 
5
#include 
6
#include "QNZBCreator.h"
7

                
8
class WidgetNZBCreatorDetails : public QObject, public QRunnable
9
{
10
    Q_OBJECT
11

                
12
public:
13
    WidgetNZBCreatorDetails(QTreeWidgetItem *item, qint64 collection_id, QDateTime stamp, QObject *parent = 0);
14

                
15
signals:
16
    void finished(bool ret, QTreeWidgetItem *item, QList files, QString errmsg);
17

                
18
private:
19
    QNZBCreator nzbcreator;
20
    QTreeWidgetItem *item;
21
    qint64 collection_id;
22
    QDateTime stamp;
23

                
24
    void run();
25
};
26

                
27
#endif // WIDGETNZBCREATORDETAILS_H
trunk/client/gui_qt/WidgetNZBCreatorDetails.cpp (revision 1833)
1
#include "WidgetNZBCreatorDetails.h"
2

                
3
WidgetNZBCreatorDetails::WidgetNZBCreatorDetails(QTreeWidgetItem *item, qint64 collection_id, QDateTime stamp, QObject *parent) :
4
    QObject(parent)
5
{
6
    qRegisterMetaType< QList >("QList");
7

                
8
    this->item = item;
9
    this->collection_id = collection_id;
10
    this->stamp = stamp;
11
}
12

                
13
void WidgetNZBCreatorDetails::run()
14
{
15
    bool ret;
16
    QString errmsg;
17
    QList files;
18

                
19
    ret = nzbcreator.retrieveAdditionalCollectionDetails(collection_id, stamp, errmsg, files);
20

                
21
    emit finished(ret, item, files, errmsg);
22
}
trunk/client/gui_qt/WidgetNZBCreator.h (revision 1833)
5 5
#include 
6 6
#include 
7 7
#include 
8
#include 
8 9
#include "QNZBCreator.h"
9 10
#include "QNNTPGrabGlue.h"
10 11
#include "ProgressBarDelegate.h"
12
#include "WidgetNZBCreatorDetails.h"
11 13

                
12 14
namespace Ui {
13 15
    class WidgetNZBCreator;
... ...
28 30
    QNZBCreator nzbcreator;
29 31
    ProgressBarDelegate *progressbarDelegate;
30 32

                
33
    /* Perform search */
31 34
    struct SearchResult {
32 35
        bool ret;
33 36
        QString errmsg;
... ...
39 42

                
40 43
    WidgetNZBCreator::SearchResult performSearch(QNZBCreator::SearchOpts opts);
41 44

                
42
    struct DetailsResult {
43
        bool ret;
44
        QString errmsg;
45
        QTreeWidgetItem *item;
46
        QList files;
47
    };
45
    /* Retrieve collection details */
46
    QThreadPool pool_details;
47
    void performGetDetails(QTreeWidgetItem *item, int collection_id, QDateTime stamp);
48 48

                
49
    QFuture future_details;
50
    QFutureWatcher watcher_details;
51

                
52
    WidgetNZBCreator::DetailsResult performGetDetails(QTreeWidgetItem *item, qint64 collection_id);
53

                
49
    /* Retrieve the NZB */
54 50
    struct ImportResult {
55 51
        QString collection_name;
56 52
        QString errmsg;
... ...
72 68
    void treeWidget_expanded(QModelIndex idx);
73 69

                
74 70
    void performSearch_finished();
75
    void performGetDetails_finished();
71
    void performGetDetails_finished(bool ret, QTreeWidgetItem *item, QList files, QString errmsg);
76 72
    void performImport_finished();
77 73
};
78 74

                
trunk/client/gui_qt/QNZBCreator.cpp (revision 1833)
100 100
        collection.complete_percentage = collection_tmp->complete_percentage;
101 101
        collection.num_regular_files = collection_tmp->num_regular_files;
102 102
        collection.num_par2_files = collection_tmp->num_par2_files;
103
        collection.first_file_id = collection_tmp->first_file_id;
103 104

                
104 105
        result.collections.append(collection);
105 106

                
... ...
110 111
    return true;
111 112
}
112 113

                
113
bool QNZBCreator::retrieveAdditionalCollectionDetails(qint64 collection_id, QString &errmsg, QList &result)
114
bool QNZBCreator::retrieveAdditionalCollectionDetails(qint64 collection_id, QDateTime stamp, QString &errmsg, QList &result)
114 115
{
115 116
    char *errmsg_tmp = NULL;
116 117
    NGList *files_tmp;
117 118

                
118
    files_tmp = nntpgrab_utils_nzbcreator_retrieve_collection_details((ngint64) collection_id, &errmsg_tmp);
119
    files_tmp = nntpgrab_utils_nzbcreator_retrieve_collection_details((ngint64) collection_id, (time_t) stamp.toTime_t(), &errmsg_tmp);
119 120
    if (!files_tmp) {
120 121
        errmsg = errmsg_tmp;
121 122
        ng_free(errmsg_tmp);

Also available in: Unified diff