ViewTransfers.cpp 28.4 KB
Newer Older
1
// This file is part of BOINC.
David Anderson's avatar
David Anderson committed
2
// http://boinc.berkeley.edu
3
// Copyright (C) 2008 University of California
Rom Walton's avatar
Rom Walton committed
4
//
5
6
7
8
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
Rom Walton's avatar
Rom Walton committed
9
//
10
// BOINC is distributed in the hope that it will be useful,
David Anderson's avatar
David Anderson committed
11
12
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
Rom Walton's avatar
Rom Walton committed
14
//
15
16
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
Rom Walton's avatar
Rom Walton committed
17

Rom Walton's avatar
Rom Walton committed
18
#if defined(__GNUG__) && !defined(__APPLE__)
Rom Walton's avatar
Rom Walton committed
19
#pragma implementation "ViewTransfers.h"
Rom Walton's avatar
Rom Walton committed
20
21
#endif

Rom Walton's avatar
Rom Walton committed
22
#include "stdwx.h"
Rom Walton's avatar
Rom Walton committed
23
#include "BOINCGUIApp.h"
Rom Walton's avatar
Rom Walton committed
24
#include "BOINCBaseFrame.h"
Rom Walton's avatar
Rom Walton committed
25
#include "MainDocument.h"
Rom Walton's avatar
Rom Walton committed
26
#include "AdvancedFrame.h"
Rom Walton's avatar
Rom Walton committed
27
28
#include "BOINCTaskCtrl.h"
#include "BOINCListCtrl.h"
Rom Walton's avatar
Rom Walton committed
29
#include "ViewTransfers.h"
30
#include "Events.h"
Rom Walton's avatar
Rom Walton committed
31
#include "error_numbers.h"
Rom Walton's avatar
Rom Walton committed
32

Rom Walton's avatar
Rom Walton committed
33

Rom Walton's avatar
Rom Walton committed
34
#include "res/xfer.xpm"
Rom Walton's avatar
Rom Walton committed
35
36


37
38
39
40
41
42
43
// Column IDs must be equal to the column's default
// position (left to right, zero-based) when all
// columns are shown.  However, any column may be
// hidden, either by default or by the user.
// (On MS Windows only, the user can also rearrange
// the columns from the default order.)
//
44
// Column IDs
Rom Walton's avatar
Rom Walton committed
45
46
47
48
49
50
51
52
#define COLUMN_PROJECT              0
#define COLUMN_FILE                 1
#define COLUMN_PROGRESS             2
#define COLUMN_SIZE                 3
#define COLUMN_TIME                 4
#define COLUMN_SPEED                5
#define COLUMN_STATUS               6

53
54
55
56
57
58
// DefaultShownColumns is an array containing the
// columnIDs of the columns to be shown by default,
// in ascending order.  It may or may not include
// all columns.
//
// For now, show all columns by default
59
60
static int DefaultShownColumns[] = { COLUMN_PROJECT, COLUMN_FILE, COLUMN_PROGRESS, 
                                COLUMN_SIZE, COLUMN_TIME, COLUMN_SPEED,
61
62
                                COLUMN_STATUS};

Rom Walton's avatar
Rom Walton committed
63
64
65
66
// buttons in the "tasks" area
#define BTN_RETRY       0
#define BTN_ABORT       1

Rom Walton's avatar
Rom Walton committed
67

David Anderson's avatar
David Anderson committed
68
CTransfer::CTransfer() {
69
70
71
72
73
    m_fProgress = -1.0;
    m_fBytesXferred = -1.0;
    m_fTotalBytes = -1.0;
    m_dTime = -1.0;
    m_dSpeed = -1.0;
Rom Walton's avatar
Rom Walton committed
74
75
76
}


David Anderson's avatar
David Anderson committed
77
CTransfer::~CTransfer() {
Rom Walton's avatar
Rom Walton committed
78
79
80
81
82
83
    m_strProjectName.Clear();
    m_strFileName.Clear();
    m_strStatus.Clear();
}


Rom Walton's avatar
Rom Walton committed
84
IMPLEMENT_DYNAMIC_CLASS(CViewTransfers, CBOINCBaseView)
Rom Walton's avatar
Rom Walton committed
85

Rom Walton's avatar
Rom Walton committed
86
87
88
BEGIN_EVENT_TABLE (CViewTransfers, CBOINCBaseView)
    EVT_BUTTON(ID_TASK_TRANSFERS_RETRYNOW, CViewTransfers::OnTransfersRetryNow)
    EVT_BUTTON(ID_TASK_TRANSFERS_ABORT, CViewTransfers::OnTransfersAbort)
Charlie Fenton's avatar
Charlie Fenton committed
89
90
91
// We currently handle EVT_LIST_CACHE_HINT on Windows or 
// EVT_CHECK_SELECTION_CHANGED on Mac & Linux instead of EVT_LIST_ITEM_SELECTED
// or EVT_LIST_ITEM_DESELECTED.  See CBOINCBaseView::OnCacheHint() for info.
92
#if USE_LIST_CACHE_HINT
93
    EVT_LIST_CACHE_HINT(ID_LIST_TRANSFERSVIEW, CViewTransfers::OnCacheHint)
94
#else
95
	EVT_CHECK_SELECTION_CHANGED(CViewTransfers::OnCheckSelectionChanged)
96
#endif
97
    EVT_LIST_COL_CLICK(ID_LIST_TRANSFERSVIEW, CViewTransfers::OnColClick)
98
    EVT_LIST_COL_END_DRAG(ID_LIST_TRANSFERSVIEW, CViewTransfers::OnColResize)
Rom Walton's avatar
Rom Walton committed
99
100
END_EVENT_TABLE ()

Rom Walton's avatar
Rom Walton committed
101

102
103
static CViewTransfers* MyCViewTransfers;

104
static bool CompareViewTransferItems(int iRowIndex1, int iRowIndex2) {
105
106
    CTransfer*      transfer1;
    CTransfer*      transfer2;
107
    int             result = 0;
108
109
110
111
112
113
114
115
116
117
118
119
120

    try {
        transfer1 = MyCViewTransfers->m_TransferCache.at(iRowIndex1);
    } catch ( std::out_of_range ) {
        return 0;
    }

    try {
        transfer2 = MyCViewTransfers->m_TransferCache.at(iRowIndex2);
    } catch ( std::out_of_range ) {
        return 0;
    }

121
    switch (MyCViewTransfers->m_iSortColumnID) {
122
123
    case COLUMN_PROJECT:
        result = transfer1->m_strProjectName.CmpNoCase(transfer2->m_strProjectName);
124
125
        break;
    case COLUMN_FILE:
126
        result = transfer1->m_strFileName.CmpNoCase(transfer2->m_strFileName);
127
128
129
130
131
132
133
134
135
        break;
    case COLUMN_PROGRESS:
        if (transfer1->m_fProgress < transfer2->m_fProgress) {
            result = -1;
        } else if (transfer1->m_fProgress > transfer2->m_fProgress) {
            result = 1;
        }
        break;
    case COLUMN_SIZE:
136
        if (transfer1->m_fTotalBytes < transfer2->m_fTotalBytes) {
137
            result = -1;
138
        } else if (transfer1->m_fTotalBytes > transfer2->m_fTotalBytes) {
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
            result = 1;
        }
        break;
    case COLUMN_TIME:
        if (transfer1->m_dTime < transfer2->m_dTime) {
            result = -1;
        } else if (transfer1->m_dTime > transfer2->m_dTime) {
            result = 1;
        }
        break;
    case COLUMN_SPEED:
        if (transfer1->m_dSpeed < transfer2->m_dSpeed) {
            result = -1;
        } else if (transfer1->m_dSpeed > transfer2->m_dSpeed) {
            result = 1;
        }
        break;
    case COLUMN_STATUS:
	result = transfer1->m_strStatus.CmpNoCase(transfer2->m_strStatus);
        break;
    }

161
    // Always return FALSE for equality (result == 0)
162
    return (MyCViewTransfers->m_bReverseSort ? (result > 0) : (result < 0));
163
164
165
}


Rom Walton's avatar
Rom Walton committed
166
167
CViewTransfers::CViewTransfers()
{}
Rom Walton's avatar
Rom Walton committed
168
169


Rom Walton's avatar
Rom Walton committed
170
CViewTransfers::CViewTransfers(wxNotebook* pNotebook) :
171
    CBOINCBaseView(pNotebook, ID_TASK_TRANSFERSVIEW, DEFAULT_TASK_FLAGS, ID_LIST_TRANSFERSVIEW, DEFAULT_LIST_FLAGS)
Rom Walton's avatar
Rom Walton committed
172
173
174
175
{
	CTaskItemGroup* pGroup = NULL;
	CTaskItem*      pItem = NULL;

David Anderson's avatar
David Anderson committed
176
177
    wxASSERT(m_pTaskPane);
    wxASSERT(m_pListPane);
Rom Walton's avatar
Rom Walton committed
178

Rom Walton's avatar
Rom Walton committed
179
180
181
182

    //
    // Setup View
    //
David Anderson's avatar
David Anderson committed
183
	pGroup = new CTaskItemGroup( _("Commands") );
Rom Walton's avatar
Rom Walton committed
184
185
186
187
	m_TaskGroups.push_back( pGroup );

	pItem = new CTaskItem(
        _("Retry Now"),
188
        _("Retry the file transfer now"),
Rom Walton's avatar
Rom Walton committed
189
190
191
        ID_TASK_TRANSFERS_RETRYNOW 
    );
    pGroup->m_Tasks.push_back( pItem );
Rom Walton's avatar
Rom Walton committed
192

Rom Walton's avatar
Rom Walton committed
193
194
	pItem = new CTaskItem(
        _("Abort Transfer"),
195
        _("Abort this file transfer.  You won't get credit for the task."),
Rom Walton's avatar
Rom Walton committed
196
197
198
        ID_TASK_TRANSFERS_ABORT 
    );
    pGroup->m_Tasks.push_back( pItem );
Rom Walton's avatar
Rom Walton committed
199
200


Rom Walton's avatar
Rom Walton committed
201
    // Create Task Pane Items
Rom Walton's avatar
Rom Walton committed
202
    m_pTaskPane->UpdateControls();
Rom Walton's avatar
Rom Walton committed
203

204
205
206
207
    // m_aStdColNameOrder is an array of all column heading labels
    // (localized) in order of ascending Column ID.
    // Once initialized, it should not be modified.
    //
208
    m_aStdColNameOrder = new wxArrayString;
209
210
211
212
213
214
215
216
    m_aStdColNameOrder->Insert(_("Project"), COLUMN_PROJECT);
    m_aStdColNameOrder->Insert(_("File"), COLUMN_FILE);
    m_aStdColNameOrder->Insert(_("Progress"), COLUMN_PROGRESS);
    m_aStdColNameOrder->Insert(_("Size"), COLUMN_SIZE);
    m_aStdColNameOrder->Insert(_("Elapsed"), COLUMN_TIME);
    m_aStdColNameOrder->Insert(_("Speed"), COLUMN_SPEED);
    m_aStdColNameOrder->Insert(_("Status"), COLUMN_STATUS);

217
    // m_iStdColWidthOrder is an array of the width for each column.
218
219
220
    // Entries must be in order of ascending Column ID.  We initalize
    // it here to the default column widths.  It is updated by
    // CBOINCListCtrl::OnRestoreState() and also when a user resizes
221
    // a column by dragging the divider between two columns.
222
    //
223
224
225
226
227
228
229
230
231
    m_iStdColWidthOrder.Clear();
    m_iStdColWidthOrder.Insert(125, COLUMN_PROJECT);
    m_iStdColWidthOrder.Insert(205, COLUMN_FILE);
    m_iStdColWidthOrder.Insert(60, COLUMN_PROGRESS);
    m_iStdColWidthOrder.Insert(80, COLUMN_SIZE);
    m_iStdColWidthOrder.Insert(80, COLUMN_TIME);
    m_iStdColWidthOrder.Insert(80, COLUMN_SPEED);
    m_iStdColWidthOrder.Insert(150, COLUMN_STATUS);

232
233
234
    m_iDefaultShownColumns = DefaultShownColumns;
    m_iNumDefaultShownColumns = sizeof(DefaultShownColumns) / sizeof(int);

235
236
    wxASSERT(m_iStdColWidthOrder.size() == m_aStdColNameOrder->size());

237
238
    m_iProgressColumn = COLUMN_PROGRESS;

239
240
241
242
    // Needed by static sort routine;
    MyCViewTransfers = this;
    m_funcSortCompare = CompareViewTransferItems;

Rom Walton's avatar
Rom Walton committed
243
    UpdateSelection();
Rom Walton's avatar
Rom Walton committed
244
245
246
}


David Anderson's avatar
David Anderson committed
247
CViewTransfers::~CViewTransfers() {
Rom Walton's avatar
Rom Walton committed
248
    EmptyCache();
Rom Walton's avatar
Rom Walton committed
249
    EmptyTasks();
Rom Walton's avatar
Rom Walton committed
250
251
252
}


253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
// Create List Pane Items
void CViewTransfers::AppendColumn(int columnID){
    switch(columnID) {
        case COLUMN_PROJECT:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_PROJECT],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_PROJECT]);
            break;
        case COLUMN_FILE:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_FILE],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_FILE]);
            break;
        case COLUMN_PROGRESS:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_PROGRESS],
                wxLIST_FORMAT_CENTRE, m_iStdColWidthOrder[COLUMN_PROGRESS]);
            break;
        case COLUMN_SIZE:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_SIZE],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_SIZE]);
            break;
        case COLUMN_TIME:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_TIME],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_TIME]);
            break;
        case COLUMN_SPEED:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_SPEED],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_SPEED]);
            break;
        case COLUMN_STATUS:
            m_pListPane->AppendColumn((*m_aStdColNameOrder)[COLUMN_STATUS],
                wxLIST_FORMAT_LEFT, m_iStdColWidthOrder[COLUMN_STATUS]);
            break;
    }
}


Rom Walton's avatar
Rom Walton committed
288
wxString& CViewTransfers::GetViewName() {
289
    static wxString strViewName(wxT("Transfers"));
Rom Walton's avatar
Rom Walton committed
290
    return strViewName;
Rom Walton's avatar
Rom Walton committed
291
}
Rom Walton's avatar
Rom Walton committed
292

Rom Walton's avatar
Rom Walton committed
293

294
295
296
297
298
299
wxString& CViewTransfers::GetViewDisplayName() {
    static wxString strViewName(_("Transfers"));
    return strViewName;
}


David Anderson's avatar
David Anderson committed
300
const char** CViewTransfers::GetViewIcon() {
Rom Walton's avatar
Rom Walton committed
301
302
303
    return xfer_xpm;
}

Rom Walton's avatar
Rom Walton committed
304

305
int CViewTransfers::GetViewCurrentViewPage() {
306
307
308
309
    return VW_XFER;
}


310
wxString CViewTransfers::GetKeyValue1(int iRowIndex) {
311
312
313
314
315
316
    CTransfer*  transfer;
    
    if (GetTransferCacheAtIndex(transfer, m_iSortedIndexes[iRowIndex])) {
        return wxEmptyString;
    }

317
318
319
320
321
322
323
324
325
    if (m_iColumnIDToColumnIndex[COLUMN_FILE] < 0) {
        // Column is hidden, so SynchronizeCacheItem() did not set its value
        wxString    strDocumentText  = wxEmptyString;
        GetDocFileName(m_iSortedIndexes[iRowIndex], strDocumentText);
        if (!strDocumentText.IsSameAs(transfer->m_strFileName)) {
            transfer->m_strFileName = strDocumentText;
        }
    }

326
327
328
329
330
    return transfer->m_strFileName;
}


wxString CViewTransfers::GetKeyValue2(int iRowIndex) {
331
332
333
334
335
336
    CTransfer*  transfer;
    
    if (GetTransferCacheAtIndex(transfer, m_iSortedIndexes[iRowIndex])) {
        return wxEmptyString;
    }
    
337
338
339
340
341
342
343
344
345
    if (m_iColumnIDToColumnIndex[COLUMN_PROJECT] < 0) {
        // Column is hidden, so SynchronizeCacheItem() did not set its value
        wxString    strDocumentText  = wxEmptyString;
        GetDocProjectURL(m_iSortedIndexes[iRowIndex], strDocumentText);
        if (!strDocumentText.IsSameAs(transfer->m_strProjectURL)) {
            transfer->m_strProjectURL = strDocumentText;
        }
    }

346
347
348
349
350
351
352
353
    return transfer->m_strProjectURL;
}


int CViewTransfers::FindRowIndexByKeyValues(wxString& key1, wxString& key2) {
    CTransfer*  transfer;
    unsigned int iRowIndex, n = GetCacheCount();
	for(iRowIndex=0; iRowIndex < n; iRowIndex++) {
354
355
356
        if (GetTransferCacheAtIndex(transfer, m_iSortedIndexes[iRowIndex])) {
            continue;
        }
357
358
359
360
361
362
363
        if(! (transfer->m_strFileName).IsSameAs(key1)) continue;
        if((transfer->m_strProjectURL).IsSameAs(key2)) return iRowIndex;
	}
	return -1;
}


Rom Walton's avatar
Rom Walton committed
364
void CViewTransfers::OnTransfersRetryNow( wxCommandEvent& WXUNUSED(event) ) {
Rom Walton's avatar
Rom Walton committed
365
366
    wxLogTrace(wxT("Function Start/End"), wxT("CViewTransfers::OnTransfersRetryNow - Function Begin"));

367
368
    CMainDocument*  pDoc    = wxGetApp().GetDocument();
    CAdvancedFrame* pFrame  = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame);
369
    int row;
Rom Walton's avatar
Rom Walton committed
370

David Anderson's avatar
David Anderson committed
371
    wxASSERT(pDoc);
Rom Walton's avatar
Rom Walton committed
372
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
David Anderson's avatar
David Anderson committed
373
    wxASSERT(pFrame);
Rom Walton's avatar
Rom Walton committed
374
    wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame));
375
376
    wxASSERT(m_pListPane);

377
378
379
    CC_STATUS status;
    pDoc->GetCoreClientStatus(status);
    if (status.network_suspend_reason) {
380
381
382
        wxString msg = _("Network activity is suspended - ");
        msg += suspend_reason_wxstring(status.network_suspend_reason);
        msg += _(".\nYou can enable it using the Activity menu.");
383
        wxGetApp().SafeMessageBox(
384
            msg,
385
386
387
388
389
390
391
            _("BOINC"),
            wxOK | wxICON_INFORMATION,
            this
        );
        return;
    }

Rom Walton's avatar
Rom Walton committed
392
    pFrame->UpdateStatusText(_("Retrying transfer now..."));
393
394
395
396
397
398
399
400
    row = -1;
    while (1) {
        // Step through all selected items
        row = m_pListPane->GetNextItem(row, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
        if (row < 0) break;
        
        pDoc->TransferRetryNow(m_iSortedIndexes[row]);
    }
Rom Walton's avatar
Rom Walton committed
401
402
    pFrame->UpdateStatusText(wxT(""));

Rom Walton's avatar
Rom Walton committed
403
    UpdateSelection();
Rom Walton's avatar
Rom Walton committed
404
    pFrame->ResetReminderTimers();
Rom Walton's avatar
Rom Walton committed
405
    pFrame->FireRefreshView();
Rom Walton's avatar
Rom Walton committed
406

Rom Walton's avatar
Rom Walton committed
407
408
409
410
    wxLogTrace(wxT("Function Start/End"), wxT("CViewTransfers::OnTransfersRetryNow - Function End"));
}


Rom Walton's avatar
Rom Walton committed
411
void CViewTransfers::OnTransfersAbort( wxCommandEvent& WXUNUSED(event) ) {
Rom Walton's avatar
Rom Walton committed
412
413
    wxLogTrace(wxT("Function Start/End"), wxT("CViewTransfers::OnTransfersAbort - Function Begin"));

414
415
416
417
418
    wxInt32         iAnswer    = 0; 
    wxString        strMessage = wxEmptyString;
    CMainDocument*  pDoc       = wxGetApp().GetDocument();
    CAdvancedFrame* pFrame     = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame);
    CTransfer*      pTransfer  = NULL;
419
    int row;
Rom Walton's avatar
Rom Walton committed
420

David Anderson's avatar
David Anderson committed
421
    wxASSERT(pDoc);
Rom Walton's avatar
Rom Walton committed
422
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
David Anderson's avatar
David Anderson committed
423
    wxASSERT(pFrame);
Rom Walton's avatar
Rom Walton committed
424
    wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame));
425
426
    wxASSERT(m_pListPane);

Charlie Fenton's avatar
Charlie Fenton committed
427
428
429
    if (!pDoc->IsUserAuthorized())
        return;

Rom Walton's avatar
Rom Walton committed
430
431
    pFrame->UpdateStatusText(_("Aborting transfer..."));

432
433
434
435
436
437
    row = -1;
    while (1) {
        // Step through all selected items
        row = m_pListPane->GetNextItem(row, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
        if (row < 0) break;
        
438
439
440
        if (GetTransferCacheAtIndex(pTransfer, m_iSortedIndexes[row])) {
            return;
        }
441
442

        strMessage.Printf(
443
            _("Are you sure you want to abort this file transfer '%s'?\nNOTE: Aborting a transfer will invalidate a task and you\nwill not receive credit for it."), 
444
445
446
            pTransfer->m_strFileName.c_str()
        );

447
        iAnswer = wxGetApp().SafeMessageBox(
448
449
450
451
452
453
454
455
456
            strMessage,
            _("Abort File Transfer"),
            wxYES_NO | wxICON_QUESTION,
            this
        );

        if (wxYES == iAnswer) {
            pDoc->TransferAbort(m_iSortedIndexes[row]);
        }
Rom Walton's avatar
Rom Walton committed
457
    }
458
    
Rom Walton's avatar
Rom Walton committed
459
460
    pFrame->UpdateStatusText(wxT(""));

Rom Walton's avatar
Rom Walton committed
461
    UpdateSelection();
Rom Walton's avatar
Rom Walton committed
462
    pFrame->FireRefreshView();
Rom Walton's avatar
Rom Walton committed
463

Rom Walton's avatar
Rom Walton committed
464
465
466
467
    wxLogTrace(wxT("Function Start/End"), wxT("CViewTransfers::OnTransfersAbort - Function End"));
}


468
void CViewTransfers::OnColResize( wxListEvent& ) {
469
470
471
472
473
    // Register the new column widths immediately
    CAdvancedFrame* pFrame = wxDynamicCast(GetParent()->GetParent()->GetParent(), CAdvancedFrame);

    wxASSERT(pFrame);
    wxASSERT(wxDynamicCast(pFrame, CAdvancedFrame));
474
    pFrame->SaveState();
475
476
477
}


David Anderson's avatar
David Anderson committed
478
wxInt32 CViewTransfers::GetDocCount() {
Rom Walton's avatar
Rom Walton committed
479
    return wxGetApp().GetDocument()->GetTransferCount();
Rom Walton's avatar
Rom Walton committed
480
481
482
}


David Anderson's avatar
David Anderson committed
483
wxString CViewTransfers::OnListGetItemText(long item, long column) const {
484
    CTransfer* transfer;
Rom Walton's avatar
Rom Walton committed
485
    wxString   strBuffer  = wxEmptyString;
Rom Walton's avatar
Rom Walton committed
486

487
    m_pListPane->AddPendingProgressBar(item);
488

489
490
491
492
493
494
    try {
        transfer = m_TransferCache.at(m_iSortedIndexes[item]);
    } catch ( std::out_of_range ) {
        transfer = NULL;
    }

495
496
    if (transfer && (column >= 0)) {
        switch(m_iColumnIndexToColumnID[column]) {
Rom Walton's avatar
Rom Walton committed
497
        case COLUMN_PROJECT:
498
            strBuffer = transfer->m_strProjectName;
Rom Walton's avatar
Rom Walton committed
499
500
            break;
        case COLUMN_FILE:
501
            strBuffer = transfer->m_strFileName;
Rom Walton's avatar
Rom Walton committed
502
503
            break;
        case COLUMN_PROGRESS:
Charlie Fenton's avatar
Charlie Fenton committed
504
            // CBOINCListCtrl::DrawProgressBars() will draw this using 
505
506
507
            // data provided by GetProgressText() and GetProgressValue(), 
            // but we need it here for accessibility programs.
            strBuffer = transfer->m_strProgress;
Rom Walton's avatar
Rom Walton committed
508
509
            break;
        case COLUMN_SIZE:
510
            strBuffer = transfer->m_strSize;
Rom Walton's avatar
Rom Walton committed
511
512
            break;
        case COLUMN_TIME:
513
            strBuffer = transfer->m_strTime;
Rom Walton's avatar
Rom Walton committed
514
515
            break;
        case COLUMN_SPEED:
516
            strBuffer = transfer->m_strSpeed;
Rom Walton's avatar
Rom Walton committed
517
518
            break;
        case COLUMN_STATUS:
519
            strBuffer = transfer->m_strStatus;
Rom Walton's avatar
Rom Walton committed
520
            break;
521
        }
Rom Walton's avatar
Rom Walton committed
522
    }
Rom Walton's avatar
Rom Walton committed
523

Rom Walton's avatar
Rom Walton committed
524
525
526
    return strBuffer;
}

Rom Walton's avatar
Rom Walton committed
527

David Anderson's avatar
David Anderson committed
528
wxInt32 CViewTransfers::AddCacheElement() {
Rom Walton's avatar
Rom Walton committed
529
    CTransfer* pItem = new CTransfer();
David Anderson's avatar
David Anderson committed
530
531
    wxASSERT(pItem);
    if (pItem) {
David Anderson's avatar
David Anderson committed
532
        m_TransferCache.push_back(pItem);
533
        m_iSortedIndexes.Add((int)m_TransferCache.size()-1);
Rom Walton's avatar
Rom Walton committed
534
535
536
537
538
539
        return 0;
    }
    return -1;
}


David Anderson's avatar
David Anderson committed
540
wxInt32 CViewTransfers::EmptyCache() {
Rom Walton's avatar
Rom Walton committed
541
542
543
544
    unsigned int i;
    for (i=0; i<m_TransferCache.size(); i++) {
        delete m_TransferCache[i];
    }
Rom Walton's avatar
Rom Walton committed
545
    m_TransferCache.clear();
546
    m_iSortedIndexes.Clear();
Rom Walton's avatar
Rom Walton committed
547
548
549
550
    return 0;
}


David Anderson's avatar
David Anderson committed
551
wxInt32 CViewTransfers::GetCacheCount() {
Rom Walton's avatar
Rom Walton committed
552
    return (wxInt32)m_TransferCache.size();
Rom Walton's avatar
Rom Walton committed
553
554
555
}


David Anderson's avatar
David Anderson committed
556
wxInt32 CViewTransfers::RemoveCacheElement() {
557
    unsigned int i;
Rom Walton's avatar
Rom Walton committed
558
    delete m_TransferCache.back();
David Anderson's avatar
David Anderson committed
559
    m_TransferCache.erase(m_TransferCache.end() - 1);
560
561
562
563
    m_iSortedIndexes.Clear();
    for (i=0; i<m_TransferCache.size(); i++) {
        m_iSortedIndexes.Add(i);
    }
Rom Walton's avatar
Rom Walton committed
564
565
566
567
    return 0;
}


568
bool CViewTransfers::IsSelectionManagementNeeded() {
569
570
571
572
    return true;
}


573
574
void CViewTransfers::UpdateSelection() {
    CTaskItemGroup* pGroup = m_TaskGroups[0];
Rom Walton's avatar
Rom Walton committed
575

576
577
578
579
580
581
582
583
584
585
586
587
588
589
    CBOINCBaseView::PreUpdateSelection();

    if (m_pListPane->GetSelectedItemCount()) {
        m_pTaskPane->EnableTaskGroupTasks(pGroup);
    } else {
        m_pTaskPane->DisableTaskGroupTasks(pGroup);
    }

    CBOINCBaseView::PostUpdateSelection();
}


bool CViewTransfers::SynchronizeCacheItem(wxInt32 iRowIndex, wxInt32 iColumnIndex) {
    wxString    strDocumentText  = wxEmptyString;
590
    wxString    strDocumentText2 = wxEmptyString;
591
    double       x = 0.0;
592
    double      fDocumentDouble = 0.0, fDocumentDouble2 = 0.0;
593
    CTransfer*  transfer;
594
595
596
597
    bool        bNeedRefresh = false;

    strDocumentText.Empty();

598
599
600
601
    if (GetTransferCacheAtIndex(transfer, m_iSortedIndexes[iRowIndex])) {
        return false;
    }

602
603
604
    if (iColumnIndex < 0) return false;

    switch (m_iColumnIndexToColumnID[iColumnIndex]) {
Rom Walton's avatar
Rom Walton committed
605
        case COLUMN_PROJECT:
606
            GetDocProjectName(m_iSortedIndexes[iRowIndex], strDocumentText);
607
608
            GetDocProjectURL(m_iSortedIndexes[iRowIndex], strDocumentText2);
            if (!strDocumentText.IsSameAs(transfer->m_strProjectName) || !strDocumentText2.IsSameAs(transfer->m_strProjectURL)) {
609
                transfer->m_strProjectName = strDocumentText;
610
                transfer->m_strProjectURL = strDocumentText2;
611
612
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
613
614
            break;
        case COLUMN_FILE:
615
616
617
618
619
            GetDocFileName(m_iSortedIndexes[iRowIndex], strDocumentText);
            if (!strDocumentText.IsSameAs(transfer->m_strFileName)) {
                transfer->m_strFileName = strDocumentText;
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
620
621
            break;
        case COLUMN_PROGRESS:
622
623
624
625
            GetDocProgress(m_iSortedIndexes[iRowIndex], x);
            if (x != transfer->m_fProgress) {
                transfer->m_fProgress = x;
                FormatProgress(x, transfer->m_strProgress);
626
627
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
628
629
            break;
        case COLUMN_SIZE:
630
            GetDocBytesXferred(m_iSortedIndexes[iRowIndex], fDocumentDouble);
631
632
633
634
            GetDocTotalBytes(m_iSortedIndexes[iRowIndex], fDocumentDouble2);
            if (( fDocumentDouble != transfer->m_fBytesXferred) || 
                (fDocumentDouble2 != transfer->m_fTotalBytes)
                ) {
635
                transfer->m_fBytesXferred = fDocumentDouble;
636
637
                transfer->m_fTotalBytes = fDocumentDouble2;
                FormatSize(fDocumentDouble, fDocumentDouble2, transfer->m_strSize);
638
639
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
640
641
            break;
        case COLUMN_TIME:
642
643
644
            GetDocTime(m_iSortedIndexes[iRowIndex], fDocumentDouble);
            if (fDocumentDouble != transfer->m_dTime) {
                transfer->m_dTime = fDocumentDouble;
645
                transfer->m_strTime = FormatTime(fDocumentDouble);
646
647
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
648
649
            break;
        case COLUMN_SPEED:
650
651
652
            GetDocSpeed(m_iSortedIndexes[iRowIndex], fDocumentDouble);
            if (fDocumentDouble != transfer->m_dSpeed) {
                transfer->m_dSpeed = fDocumentDouble;
653
                FormatSpeed(fDocumentDouble, transfer->m_strSpeed);
654
655
                bNeedRefresh =  true;
            }
Rom Walton's avatar
Rom Walton committed
656
657
            break;
        case COLUMN_STATUS:
658
659
660
661
662
            GetDocStatus(m_iSortedIndexes[iRowIndex], strDocumentText);
            if (!strDocumentText.IsSameAs(transfer->m_strStatus)) {
                transfer->m_strStatus = strDocumentText;
                return true;
            }
Rom Walton's avatar
Rom Walton committed
663
664
665
            break;
    }

666
    return bNeedRefresh;
Rom Walton's avatar
Rom Walton committed
667
668
669
}


670
void CViewTransfers::GetDocProjectName(wxInt32 item, wxString& strBuffer) const {
671
672
673
674
675
676
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
Rom Walton's avatar
Rom Walton committed
677

678
    if (transfer) {
679
        strBuffer = HtmlEntityDecode(wxString(transfer->project_name.c_str(), wxConvUTF8));
Rom Walton's avatar
Rom Walton committed
680
    } else {
681
        strBuffer = wxEmptyString;
Rom Walton's avatar
Rom Walton committed
682
    }
Rom Walton's avatar
Rom Walton committed
683
684
685
}


686
void CViewTransfers::GetDocFileName(wxInt32 item, wxString& strBuffer) const {
687
688
689
690
691
692
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
Rom Walton's avatar
Rom Walton committed
693

Rom Walton's avatar
Rom Walton committed
694
    if (transfer) {
Rom Walton's avatar
Rom Walton committed
695
        strBuffer = wxString(transfer->name.c_str(), wxConvUTF8);
696
697
    } else {
        strBuffer = wxEmptyString;
Rom Walton's avatar
Rom Walton committed
698
    }
699
700
701
}


702
703
704
void CViewTransfers::GetDocProgress(wxInt32 item, double& fBuffer) const {
    double          fBytesSent = 0;
    double          fFileSize = 0;
705
706
707
708
709
710
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
Rom Walton's avatar
Rom Walton committed
711

712
    fBuffer = 0;
Rom Walton's avatar
Rom Walton committed
713
    if (transfer) {
Rom Walton's avatar
Rom Walton committed
714
        fBytesSent = transfer->bytes_xferred;
Rom Walton's avatar
Rom Walton committed
715
716
        fFileSize = transfer->nbytes;
    }
Rom Walton's avatar
Rom Walton committed
717

David Anderson's avatar
David Anderson committed
718
719
720
721
722
723
724
    // Curl apparently counts the HTTP header in byte count.
    // Prevent this from causing > 100% display
    //
    if (fBytesSent > fFileSize) {
        fBytesSent = fFileSize;
    }

725
726
    if (fFileSize) {
        fBuffer = floor((fBytesSent / fFileSize) * 10000)/100;
Rom Walton's avatar
Rom Walton committed
727
    }
728
729
}

Rom Walton's avatar
Rom Walton committed
730

731
wxInt32 CViewTransfers::FormatProgress(double fBuffer, wxString& strBuffer) const {
732
    strBuffer.Printf(wxT("%.2f%%"), fBuffer);
Rom Walton's avatar
Rom Walton committed
733
734
735
736
    return 0;
}


737
void CViewTransfers::GetDocBytesXferred(wxInt32 item, double& fBuffer) const {
738
739
740
741
742
743
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
Rom Walton's avatar
Rom Walton committed
744

Rom Walton's avatar
Rom Walton committed
745
    if (transfer) {
746
747
748
        fBuffer = transfer->bytes_xferred;
    } else {
        fBuffer = 0.0;
Rom Walton's avatar
Rom Walton committed
749
    }
750
751
752
753
}


void CViewTransfers::GetDocTotalBytes(wxInt32 item, double& fBuffer) const {
754
755
756
757
758
759
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
760
761
762
763
764
765
766
767
768

    if (transfer) {
        fBuffer = transfer->nbytes;
    } else {
        fBuffer = 0.0;
    }
}


769
wxInt32 CViewTransfers::FormatSize(double fBytesSent, double fFileSize, wxString& strBuffer) const {
770
771
772
773
    double          xTera = 1099511627776.0;
    double          xGiga = 1073741824.0;
    double          xMega = 1048576.0;
    double          xKilo = 1024.0;
David Anderson's avatar
David Anderson committed
774
775
776
777
778
779
780
781
782
783
784
785

    if (fFileSize != 0) {
        if      (fFileSize >= xTera) {
            strBuffer.Printf(wxT("%0.2f/%0.2f TB"), fBytesSent/xTera, fFileSize/xTera);
        } else if (fFileSize >= xGiga) {
            strBuffer.Printf(wxT("%0.2f/%0.2f GB"), fBytesSent/xGiga, fFileSize/xGiga);
        } else if (fFileSize >= xMega) {
            strBuffer.Printf(wxT("%0.2f/%0.2f MB"), fBytesSent/xMega, fFileSize/xMega);
        } else if (fFileSize >= xKilo) {
            strBuffer.Printf(wxT("%0.2f/%0.2f KB"), fBytesSent/xKilo, fFileSize/xKilo);
        } else {
            strBuffer.Printf(wxT("%0.0f/%0.0f bytes"), fBytesSent, fFileSize);
Rom Walton's avatar
Rom Walton committed
786
        }
David Anderson's avatar
David Anderson committed
787
788
789
790
791
792
793
794
795
796
797
    } else {
        if      (fBytesSent >= xTera) {
            strBuffer.Printf(wxT("%0.2f TB"), fBytesSent/xTera);
        } else if (fBytesSent >= xGiga) {
            strBuffer.Printf(wxT("%0.2f GB"), fBytesSent/xGiga);
        } else if (fBytesSent >= xMega) {
            strBuffer.Printf(wxT("%0.2f MB"), fBytesSent/xMega);
        } else if (fBytesSent >= xKilo) {
            strBuffer.Printf(wxT("%0.2f KB"), fBytesSent/xKilo);
        } else {
            strBuffer.Printf(wxT("%0.0f bytes"), fBytesSent);
Rom Walton's avatar
Rom Walton committed
798
799
        }
    }
Rom Walton's avatar
Rom Walton committed
800

Rom Walton's avatar
Rom Walton committed
801
802
803
804
    return 0;
}


805
void CViewTransfers::GetDocTime(wxInt32 item, double& fBuffer) const {
806
807
808
809
810
811
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
812
813
814
815
816
817
818
819
820

    if (transfer) {
        fBuffer = transfer->time_so_far;
    } else {
        fBuffer = 0.0;
    }
}

void CViewTransfers::GetDocSpeed(wxInt32 item, double& fBuffer) const {
821
822
823
824
825
826
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
Rom Walton's avatar
Rom Walton committed
827

Rom Walton's avatar
Rom Walton committed
828
829
    if (transfer) {
        if (transfer->xfer_active)
830
            fBuffer = transfer->xfer_speed / 1024;
Rom Walton's avatar
Rom Walton committed
831
        else
832
            fBuffer = 0.0;
David Anderson's avatar
David Anderson committed
833
    }
834
}
Rom Walton's avatar
Rom Walton committed
835

836

837
838
wxInt32 CViewTransfers::FormatSpeed(double fBuffer, wxString& strBuffer) const {
    strBuffer.Printf(wxT("%.2f KBps"), fBuffer);
Rom Walton's avatar
Rom Walton committed
839

Rom Walton's avatar
Rom Walton committed
840
841
842
843
    return 0;
}


844
void CViewTransfers::GetDocStatus(wxInt32 item, wxString& strBuffer) const {
845
846
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
847
848
    int retval;
    strBuffer = wxString("", wxConvUTF8);
849
    
850
851
    transfer = pDoc->file_transfer(item);
    if (!transfer) return;
Rom Walton's avatar
Rom Walton committed
852
    CC_STATUS      status;
Rom Walton's avatar
Rom Walton committed
853

854
855
    wxASSERT(pDoc);
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
Rom Walton's avatar
Rom Walton committed
856

857
    retval = pDoc->GetCoreClientStatus(status);
858
    if (retval) return;
Rom Walton's avatar
Rom Walton committed
859

Rom Walton's avatar
Rom Walton committed
860
    wxDateTime dtNextRequest((time_t)transfer->next_request_time);
Rom Walton's avatar
Rom Walton committed
861
862
    wxDateTime dtNow(wxDateTime::Now());

863
864
865
866
867
868
869
870
871
872
873
874
    strBuffer = transfer->is_upload?_("Upload"):_("Download");
    strBuffer += wxString(": ", wxConvUTF8);
    if (dtNextRequest > dtNow) {
        wxTimeSpan tsNextRequest(dtNextRequest - dtNow);
        strBuffer += _("retry in ") + tsNextRequest.Format();
    } else if (transfer->status == ERR_GIVEUP_DOWNLOAD || transfer->status == ERR_GIVEUP_UPLOAD) {
        strBuffer = _("failed");
    } else {
        if (status.network_suspend_reason) {
            strBuffer += _("suspended");
            strBuffer += wxString(" - ", wxConvUTF8);
            strBuffer += suspend_reason_wxstring(status.network_suspend_reason);
David Anderson's avatar
David Anderson committed
875
        } else {
876
877
            if (transfer->xfer_active) {
                strBuffer += _("active");
Rom Walton's avatar
Rom Walton committed
878
            } else {
879
                strBuffer += _("pending");
Rom Walton's avatar
Rom Walton committed
880
            }
Rom Walton's avatar
Rom Walton committed
881
        }
882
883
    }
    if (transfer->project_backoff) {
884
        wxString x = FormatTime(transfer->project_backoff);
885
        strBuffer += _(" (project backoff: ") + x + _(")");
Rom Walton's avatar
Rom Walton committed
886
    }
887
888
889
}


890
void CViewTransfers::GetDocProjectURL(wxInt32 item, wxString& strBuffer) const {
891
892
893
894
895
896
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(item);
    }
897
898
899
900
901
902
903
904
905

    wxASSERT(transfer);

    if (transfer) {
        strBuffer = wxString(transfer->project_url.c_str(), wxConvUTF8);
    }
}


906
double CViewTransfers::GetProgressValue(long item) {
907
908
    double          fBytesSent = 0;
    double          fFileSize = 0;
909
910
911
912
913
914
    FILE_TRANSFER* transfer = NULL;
    CMainDocument* pDoc = wxGetApp().GetDocument();
    
    if (pDoc) {
        transfer = pDoc->file_transfer(m_iSortedIndexes[item]);
    }
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933

    if (transfer) {
        fBytesSent = transfer->bytes_xferred;
        fFileSize = transfer->nbytes;
    }

    // Curl apparently counts the HTTP header in byte count.
    // Prevent this from causing > 100% display
    //
    if (fBytesSent > fFileSize) {
        fBytesSent = fFileSize;
    }

    if ( 0.0 == fFileSize ) return 0.0;
    
    return (fBytesSent / fFileSize);
}


934
935
936
937
wxString CViewTransfers::GetProgressText( long item) {
    CTransfer* transfer;
    wxString   strBuffer  = wxEmptyString;

938
    GetTransferCacheAtIndex(transfer, m_iSortedIndexes[item]);
939
940
941
942
943
944
945
    if (transfer) {
        strBuffer = transfer->m_strProgress;
    }
    return strBuffer;
}


946
947
948
949
950
951
952
953
954
955
956
int CViewTransfers::GetTransferCacheAtIndex(CTransfer*& transferPtr, int index) {
    try {
        transferPtr = m_TransferCache.at(index);
    } catch ( std::out_of_range ) {
        transferPtr = NULL;
        return -1;
    }
    
    return 0;
}