~ubuntu-branches/ubuntu/karmic/filezilla/karmic

« back to all changes in this revision

Viewing changes to src/interface/queue.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adrien Cunin
  • Date: 2007-07-30 18:54:13 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070730185413-p60opijyw3p4dfc2
Tags: 3.0.0~beta11-0ubuntu1
* New upstream release
* Dropped dpatch
* debian/README.Debian: dropped, the warning is not correct
* debian/filezilla-common.docs: added AUTHORS and NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "FileZilla.h"
 
2
#include "queue.h"
 
3
#include "queueview_failed.h"
 
4
#include "queueview_successful.h"
 
5
 
 
6
CQueueItem::CQueueItem()
 
7
{
 
8
        m_visibleOffspring = 0;
 
9
        m_parent = 0;
 
10
        m_maxCachedIndex = -1;
 
11
}
 
12
 
 
13
CQueueItem::~CQueueItem()
 
14
{
 
15
        std::vector<CQueueItem*>::iterator iter;
 
16
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
17
                delete *iter;
 
18
}
 
19
 
 
20
void CQueueItem::SetPriority(enum QueuePriority priority)
 
21
{
 
22
        std::vector<CQueueItem*>::iterator iter;
 
23
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
24
                (*iter)->SetPriority(priority);
 
25
}
 
26
 
 
27
void CQueueItem::AddChild(CQueueItem* item)
 
28
{
 
29
        item->m_indent = m_indent + _T("  ");
 
30
        m_children.push_back(item);
 
31
 
 
32
        m_visibleOffspring += 1 + item->m_visibleOffspring;
 
33
        m_maxCachedIndex = -1;
 
34
        CQueueItem* parent = GetParent();
 
35
        while (parent)
 
36
        {
 
37
                parent->m_visibleOffspring += 1 + item->m_visibleOffspring;
 
38
                parent->m_maxCachedIndex = -1;
 
39
                parent = parent->GetParent();
 
40
        }
 
41
}
 
42
 
 
43
CQueueItem* CQueueItem::GetChild(unsigned int item, bool recursive /*=true*/)
 
44
{
 
45
        std::vector<CQueueItem*>::iterator iter;
 
46
        if (!recursive)
 
47
        {
 
48
                if (item >= m_children.size())
 
49
                        return 0;
 
50
                iter = m_children.begin();
 
51
                iter += item;
 
52
                return *iter;
 
53
        }
 
54
 
 
55
        if ((int)item <= m_maxCachedIndex)
 
56
        {
 
57
                // Index is cached
 
58
                iter = m_children.begin();
 
59
                iter += m_lookupCache[item].child;
 
60
                item -= m_lookupCache[item].index;
 
61
                if (!item)
 
62
                        return *iter;
 
63
                else
 
64
                        return (*iter)->GetChild(item - 1);
 
65
        }
 
66
        
 
67
        int index;
 
68
        int child;
 
69
        iter = m_children.begin();
 
70
        if (m_maxCachedIndex == -1)
 
71
        {
 
72
                child = 0;
 
73
                index = 0;
 
74
        }
 
75
        else
 
76
        {
 
77
                // Start with loop with the last cached item index
 
78
                iter += m_lookupCache[m_maxCachedIndex].child + 1;
 
79
                item -= m_maxCachedIndex + 1;
 
80
                index = m_maxCachedIndex + 1;
 
81
                child = m_lookupCache[m_maxCachedIndex].child + 1;
 
82
        }
 
83
 
 
84
        for (; iter != m_children.end(); iter++, child++)
 
85
        {
 
86
                if (!item)
 
87
                        return *iter;
 
88
 
 
89
                unsigned int count = (*iter)->GetChildrenCount(true);
 
90
                if (item > count)
 
91
                {
 
92
                        if (m_maxCachedIndex == -1 && m_lookupCache.size() < (unsigned int)m_visibleOffspring)
 
93
                                m_lookupCache.resize(m_visibleOffspring);
 
94
                        for (unsigned int k = index; k <= index + count; k++)
 
95
                        {
 
96
                                m_lookupCache[k].child = child;
 
97
                                m_lookupCache[k].index = index;
 
98
                        }
 
99
                        m_maxCachedIndex = index + count;
 
100
                        item -= count + 1;
 
101
                        index += count + 1;
 
102
                        continue;
 
103
                }
 
104
 
 
105
                return (*iter)->GetChild(item - 1);
 
106
        }
 
107
        return 0;
 
108
}
 
109
 
 
110
unsigned int CQueueItem::GetChildrenCount(bool recursive)
 
111
{
 
112
        if (!recursive)
 
113
                return m_children.size();
 
114
 
 
115
        return m_visibleOffspring;
 
116
}
 
117
 
 
118
bool CQueueItem::RemoveChild(CQueueItem* pItem, bool destroy /*=true*/)
 
119
{
 
120
        int oldVisibleOffspring = m_visibleOffspring;
 
121
        std::vector<CQueueItem*>::iterator iter;
 
122
        bool deleted = false;
 
123
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
124
        {
 
125
                if (*iter == pItem)
 
126
                {
 
127
                        m_visibleOffspring -= 1;
 
128
                        m_visibleOffspring -= pItem->m_visibleOffspring;
 
129
                        if (destroy)
 
130
                                delete pItem;
 
131
                        m_children.erase(iter);
 
132
 
 
133
                        deleted = true;
 
134
                        break;
 
135
                }
 
136
 
 
137
                int visibleOffspring = (*iter)->m_visibleOffspring;
 
138
                if ((*iter)->RemoveChild(pItem, destroy))
 
139
                {
 
140
                        m_visibleOffspring -= visibleOffspring - (*iter)->m_visibleOffspring;
 
141
                        if (!(*iter)->m_children.size())
 
142
                        {
 
143
                                m_visibleOffspring -= 1;
 
144
                                delete *iter;
 
145
                                m_children.erase(iter);
 
146
                        }
 
147
 
 
148
                        deleted = true;
 
149
                        break;
 
150
                }
 
151
        }
 
152
        if (!deleted)
 
153
                return false;
 
154
 
 
155
        m_maxCachedIndex = -1;
 
156
 
 
157
        // Propagate new children count to parent
 
158
        CQueueItem* parent = GetParent();
 
159
        while (parent)
 
160
        {
 
161
                parent->m_maxCachedIndex = -1;
 
162
                parent->m_visibleOffspring -= oldVisibleOffspring - m_visibleOffspring;
 
163
                parent = parent->GetParent();
 
164
        }
 
165
 
 
166
        return true;
 
167
}
 
168
 
 
169
bool CQueueItem::TryRemoveAll()
 
170
{
 
171
        const int oldVisibleOffspring = m_visibleOffspring;
 
172
        std::vector<CQueueItem*>::iterator iter;
 
173
        std::vector<CQueueItem*> keepChildren;
 
174
        m_visibleOffspring = 0;
 
175
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
176
        {
 
177
                CQueueItem* pItem = *iter;
 
178
                if (pItem->TryRemoveAll())
 
179
                        delete pItem;
 
180
                else
 
181
                {
 
182
                        keepChildren.push_back(pItem);
 
183
                        m_visibleOffspring++;
 
184
                        m_visibleOffspring += pItem->GetChildrenCount(true);
 
185
                }
 
186
        }
 
187
        m_children = keepChildren;
 
188
        m_maxCachedIndex = -1;
 
189
 
 
190
        CQueueItem* parent = GetParent();
 
191
        while (parent)
 
192
        {
 
193
                parent->m_maxCachedIndex = -1;
 
194
                parent->m_visibleOffspring -= oldVisibleOffspring - m_visibleOffspring;
 
195
                parent = parent->GetParent();
 
196
        }
 
197
 
 
198
        return m_children.empty();
 
199
}
 
200
 
 
201
CQueueItem* CQueueItem::GetTopLevelItem()
 
202
{
 
203
        if (!m_parent)
 
204
                return this;
 
205
 
 
206
        CQueueItem* newParent = m_parent;
 
207
        CQueueItem* parent = 0;
 
208
        while (newParent)
 
209
        {
 
210
                parent = newParent;
 
211
                newParent = newParent->GetParent();
 
212
        }
 
213
 
 
214
        return parent;
 
215
}
 
216
 
 
217
const CQueueItem* CQueueItem::GetTopLevelItem() const
 
218
{
 
219
        if (!m_parent)
 
220
                return this;
 
221
 
 
222
        const CQueueItem* newParent = m_parent;
 
223
        const CQueueItem* parent = 0;
 
224
        while (newParent)
 
225
        {
 
226
                parent = newParent;
 
227
                newParent = newParent->GetParent();
 
228
        }
 
229
 
 
230
        return parent;
 
231
}
 
232
 
 
233
int CQueueItem::GetItemIndex() const
 
234
{
 
235
        const CQueueItem* pParent = GetParent();
 
236
        if (!pParent)
 
237
                return 0;
 
238
 
 
239
        int index = 1;
 
240
        for (std::vector<CQueueItem*>::const_iterator iter = pParent->m_children.begin(); iter != pParent->m_children.end(); iter++)
 
241
        {
 
242
                if (*iter == this)
 
243
                        break;
 
244
 
 
245
                index += (*iter)->GetChildrenCount(true) + 1;
 
246
        }
 
247
 
 
248
        return index + pParent->GetItemIndex();
 
249
}
 
250
 
 
251
CFileItem::CFileItem(CServerItem* parent, bool queued, bool download, const wxString& localFile,
 
252
                                         const wxString& remoteFile, const CServerPath& remotePath, wxLongLong size)
 
253
{
 
254
        m_parent = parent;
 
255
        m_priority = priority_normal;
 
256
 
 
257
        m_download = download;
 
258
        m_localFile = localFile;
 
259
        m_remoteFile = remoteFile;
 
260
        m_remotePath = remotePath;
 
261
        m_size = size;
 
262
        m_itemState = ItemState_Wait;
 
263
        m_queued = queued;
 
264
        m_active = false;
 
265
        m_errorCount = 0;
 
266
        m_remove = false;
 
267
        m_pEngineData = 0;
 
268
        m_defaultFileExistsAction = -1;
 
269
}
 
270
 
 
271
CFileItem::~CFileItem()
 
272
{
 
273
}
 
274
 
 
275
void CFileItem::SetPriority(enum QueuePriority priority)
 
276
{
 
277
        if (priority == m_priority)
 
278
                return;
 
279
 
 
280
        CServerItem* parent = (CServerItem*)m_parent;
 
281
        parent->SetChildPriority(this, m_priority, priority);
 
282
        m_priority = priority;
 
283
}
 
284
 
 
285
void CFileItem::SetPriorityRaw(enum QueuePriority priority)
 
286
{
 
287
        m_priority = priority;
 
288
}
 
289
 
 
290
enum ItemState CFileItem::GetItemState() const
 
291
{
 
292
        return m_itemState;
 
293
}
 
294
 
 
295
void CFileItem::SetItemState(const enum ItemState itemState)
 
296
{
 
297
        m_itemState = itemState;
 
298
}
 
299
 
 
300
enum QueuePriority CFileItem::GetPriority() const
 
301
{
 
302
        return m_priority;
 
303
}
 
304
 
 
305
void CFileItem::SetActive(const bool active)
 
306
{
 
307
        if (active && !m_active)
 
308
        {
 
309
                AddChild(new CStatusItem);
 
310
        }
 
311
        else if (!active && m_active)
 
312
        {
 
313
                CQueueItem* pItem = m_children.front();
 
314
                RemoveChild(pItem);
 
315
        }
 
316
        m_active = active;
 
317
}
 
318
 
 
319
void CFileItem::SaveItem(TiXmlElement* pElement) const
 
320
{
 
321
        if (GetItemState() == ItemState_Complete)
 
322
                return;
 
323
 
 
324
        //TODO: Save error items?
 
325
        TiXmlElement file("File");
 
326
 
 
327
        AddTextElement(&file, "LocalFile", m_localFile);
 
328
        AddTextElement(&file, "RemoteFile", m_remoteFile);
 
329
        AddTextElement(&file, "RemotePath", m_remotePath.GetSafePath());
 
330
        AddTextElement(&file, "Download", m_download ? _T("1") : _T("0"));
 
331
        if (m_size != -1)
 
332
                AddTextElement(&file, "Size", m_size.ToString());
 
333
        if (m_errorCount)
 
334
                AddTextElement(&file, "ErrorCount", m_errorCount);
 
335
        AddTextElement(&file, "Priority", m_priority);
 
336
        if (m_itemState)
 
337
                AddTextElement(&file, "ItemState", m_itemState);
 
338
        AddTextElement(&file, "TransferMode", m_transferSettings.binary ? _T("1") : _T("0"));
 
339
 
 
340
        pElement->InsertEndChild(file);
 
341
}
 
342
 
 
343
bool CFileItem::TryRemoveAll()
 
344
{
 
345
        if (!IsActive())
 
346
                return true;
 
347
 
 
348
        m_remove = true;
 
349
        return false;
 
350
}
 
351
 
 
352
CFolderItem::CFolderItem(CServerItem* parent, bool queued, const wxString& localFile)
 
353
        : CFileItem(parent, queued, true, localFile, _T(""), CServerPath(), -1)
 
354
{
 
355
}
 
356
 
 
357
CFolderItem::CFolderItem(CServerItem* parent, bool queued, const CServerPath& remotePath, const wxString& remoteFile)
 
358
        : CFileItem(parent, queued, false, _T(""), remoteFile, remotePath, -1)
 
359
{
 
360
}
 
361
 
 
362
void CFolderItem::SaveItem(TiXmlElement* pElement) const
 
363
{
 
364
        if (GetItemState() == ItemState_Complete ||
 
365
                GetItemState() == ItemState_Error)
 
366
                return;
 
367
 
 
368
        TiXmlElement file("Folder");
 
369
 
 
370
        if (m_download)
 
371
                AddTextElement(&file, "LocalFile", m_localFile);
 
372
        else
 
373
        {
 
374
                AddTextElement(&file, "RemoteFile", m_remoteFile);
 
375
                AddTextElement(&file, "RemotePath", m_remotePath.GetSafePath());
 
376
        }
 
377
        AddTextElement(&file, "Download", m_download ? _T("1") : _T("0"));
 
378
 
 
379
        pElement->InsertEndChild(file);
 
380
}
 
381
 
 
382
void CFolderItem::SetActive(const bool active)
 
383
{
 
384
        m_active = active;
 
385
}
 
386
 
 
387
CServerItem::CServerItem(const CServer& server)
 
388
{
 
389
        m_server = server;
 
390
        m_activeCount = 0;
 
391
}
 
392
 
 
393
CServerItem::~CServerItem()
 
394
{
 
395
}
 
396
 
 
397
const CServer& CServerItem::GetServer() const
 
398
{
 
399
        return m_server;
 
400
}
 
401
 
 
402
wxString CServerItem::GetName() const
 
403
{
 
404
        return m_server.FormatServer();
 
405
}
 
406
 
 
407
void CServerItem::AddChild(CQueueItem* pItem)
 
408
{
 
409
        CQueueItem::AddChild(pItem);
 
410
        if (pItem->GetType() == QueueItemType_File ||
 
411
                pItem->GetType() == QueueItemType_Folder)
 
412
                AddFileItemToList((CFileItem*)pItem);
 
413
}
 
414
 
 
415
void CServerItem::AddFileItemToList(CFileItem* pItem)
 
416
{
 
417
        if (!pItem)
 
418
                return;
 
419
 
 
420
        m_fileList[pItem->m_queued ? 0 : 1][pItem->GetPriority()].push_back(pItem);
 
421
}
 
422
 
 
423
void CServerItem::RemoveFileItemFromList(CFileItem* pItem)
 
424
{
 
425
        std::list<CFileItem*>& fileList = m_fileList[pItem->m_queued ? 0 : 1][pItem->GetPriority()];
 
426
        for (std::list<CFileItem*>::iterator iter = fileList.begin(); iter != fileList.end(); iter++)
 
427
        {
 
428
                if (*iter == pItem)
 
429
                {
 
430
                        fileList.erase(iter);
 
431
                        return;
 
432
                }
 
433
        }
 
434
        wxFAIL_MSG(_T("File item not deleted from m_fileList"));
 
435
}
 
436
 
 
437
void CServerItem::SetDefaultFileExistsAction(int action, const enum TransferDirection direction)
 
438
{
 
439
        for (std::vector<CQueueItem*>::iterator iter = m_children.begin(); iter != m_children.end(); iter++)
 
440
        {
 
441
                CQueueItem *pItem = *iter;
 
442
                if (pItem->GetType() == QueueItemType_File)
 
443
                {
 
444
                        CFileItem* pFileItem = ((CFileItem *)pItem);
 
445
                        if (direction == upload && pFileItem->Download())
 
446
                                continue;
 
447
                        else if (direction == download && !pFileItem->Download())
 
448
                                continue;
 
449
                        pFileItem->m_defaultFileExistsAction = action;
 
450
                }
 
451
                else if (pItem->GetType() == QueueItemType_FolderScan)
 
452
                {
 
453
                        if (direction == download)
 
454
                                continue;
 
455
                        ((CFolderScanItem *)pItem)->m_defaultFileExistsAction = action;
 
456
                }
 
457
        }
 
458
}
 
459
 
 
460
CFileItem* CServerItem::GetIdleChild(bool immediateOnly, enum TransferDirection direction)
 
461
{
 
462
        int i = 0;
 
463
        for (i = (PRIORITY_COUNT - 1); i >= 0; i--)
 
464
        {
 
465
                std::list<CFileItem*>& fileList = m_fileList[1][i];
 
466
                for (std::list<CFileItem*>::iterator iter = fileList.begin(); iter != fileList.end(); iter++)
 
467
                {
 
468
                        CFileItem* item = *iter;
 
469
                        if (item->IsActive())
 
470
                                continue;
 
471
 
 
472
                        if (direction == both)
 
473
                                return item;
 
474
 
 
475
                        if (direction == download)
 
476
                        {
 
477
                                if (item->Download())
 
478
                                        return item;
 
479
                        }
 
480
                        else if (!item->Download())
 
481
                                return item;
 
482
                }
 
483
        }
 
484
        if (immediateOnly)
 
485
                return 0;
 
486
 
 
487
        for (i = (PRIORITY_COUNT - 1); i >= 0; i--)
 
488
        {
 
489
                std::list<CFileItem*>& fileList = m_fileList[0][i];
 
490
                for (std::list<CFileItem*>::iterator iter = fileList.begin(); iter != fileList.end(); iter++)
 
491
                {
 
492
                        CFileItem* item = *iter;
 
493
                        if (item->IsActive())
 
494
                                continue;
 
495
 
 
496
                        if (direction == both)
 
497
                                return item;
 
498
 
 
499
                        if (direction == download)
 
500
                        {
 
501
                                if (item->Download())
 
502
                                        return item;
 
503
                        }
 
504
                        else if (!item->Download())
 
505
                                return item;
 
506
                }
 
507
        }
 
508
 
 
509
        return 0;
 
510
}
 
511
 
 
512
bool CServerItem::RemoveChild(CQueueItem* pItem, bool destroy /*=true*/)
 
513
{
 
514
        if (!pItem)
 
515
                return false;
 
516
 
 
517
        if (pItem->GetType() == QueueItemType_File || pItem->GetType() == QueueItemType_Folder)
 
518
        {
 
519
                CFileItem* pFileItem = reinterpret_cast<CFileItem*>(pItem);
 
520
                RemoveFileItemFromList(pFileItem);
 
521
        }
 
522
 
 
523
        return CQueueItem::RemoveChild(pItem, destroy);
 
524
}
 
525
 
 
526
void CServerItem::QueueImmediateFiles()
 
527
{
 
528
        for (int i = 0; i < PRIORITY_COUNT; i++)
 
529
        {
 
530
                std::list<CFileItem*> activeList;
 
531
                std::list<CFileItem*>& fileList = m_fileList[1][i];
 
532
                for (std::list<CFileItem*>::reverse_iterator iter = fileList.rbegin(); iter != fileList.rend(); iter++)
 
533
                {
 
534
                        CFileItem* item = *iter;
 
535
                        wxASSERT(!item->m_queued);
 
536
                        if (item->IsActive())
 
537
                                activeList.push_front(item);
 
538
                        else
 
539
                        {
 
540
                                item->m_queued = true;
 
541
                                m_fileList[0][i].push_front(item);
 
542
                        }
 
543
                }
 
544
                fileList = activeList;
 
545
        }
 
546
}
 
547
 
 
548
void CServerItem::QueueImmediateFile(CFileItem* pItem)
 
549
{
 
550
        if (pItem->m_queued)
 
551
                return;
 
552
 
 
553
        std::list<CFileItem*>& fileList = m_fileList[1][pItem->GetPriority()];
 
554
        for (std::list<CFileItem*>::iterator iter = fileList.begin(); iter != fileList.end(); iter++)
 
555
        {
 
556
                if (*iter != pItem)
 
557
                        continue;
 
558
 
 
559
                pItem->m_queued = true;
 
560
                fileList.erase(iter);
 
561
                m_fileList[0][pItem->GetPriority()].push_front(pItem);
 
562
                return;
 
563
        }
 
564
        wxASSERT(false);
 
565
}
 
566
 
 
567
void CServerItem::SaveItem(TiXmlElement* pElement) const
 
568
{
 
569
        TiXmlElement server("Server");
 
570
        SetServer(&server, m_server);
 
571
 
 
572
        for (std::vector<CQueueItem*>::const_iterator iter = m_children.begin(); iter != m_children.end(); iter++)
 
573
                (*iter)->SaveItem(&server);
 
574
 
 
575
        pElement->InsertEndChild(server);
 
576
}
 
577
 
 
578
wxLongLong CServerItem::GetTotalSize(int& filesWithUnknownSize, int& queuedFiles, int& folderScanCount) const
 
579
{
 
580
        wxLongLong totalSize = 0;
 
581
        for (int i = 0; i < PRIORITY_COUNT; i++)
 
582
        {
 
583
                for (int j = 0; j < 2; j++)
 
584
                {
 
585
                        const std::list<CFileItem*>& fileList = m_fileList[j][i];
 
586
                        for (std::list<CFileItem*>::const_iterator iter = fileList.begin(); iter != fileList.end(); iter++)
 
587
                        {
 
588
                                const CFileItem* item = *iter;
 
589
                                if (item->GetItemState() != ItemState_Complete)
 
590
                                {
 
591
                                        wxLongLong size = item->GetSize();
 
592
                                        if (size >= 0)
 
593
                                                totalSize += size;
 
594
                                        else
 
595
                                                filesWithUnknownSize++;
 
596
                                }
 
597
                        }
 
598
                }
 
599
        }
 
600
 
 
601
        for (std::vector<CQueueItem*>::const_iterator iter = m_children.begin(); iter != m_children.end(); iter++)
 
602
        {
 
603
                if ((*iter)->GetType() == QueueItemType_File ||
 
604
                        (*iter)->GetType() == QueueItemType_Folder)
 
605
                        queuedFiles++;
 
606
                else if ((*iter)->GetType() == QueueItemType_FolderScan)
 
607
                        folderScanCount++;
 
608
        }
 
609
 
 
610
        return totalSize;
 
611
}
 
612
 
 
613
bool CServerItem::TryRemoveAll()
 
614
{
 
615
        const int oldVisibleOffspring = m_visibleOffspring;
 
616
        std::vector<CQueueItem*>::iterator iter;
 
617
        std::vector<CQueueItem*> keepChildren;
 
618
        m_visibleOffspring = 0;
 
619
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
620
        {
 
621
                CQueueItem* pItem = *iter;
 
622
                if (pItem->TryRemoveAll())
 
623
                {
 
624
                        if (pItem->GetType() == QueueItemType_File || pItem->GetType() == QueueItemType_Folder)
 
625
                        {
 
626
                                CFileItem* pFileItem = reinterpret_cast<CFileItem*>(pItem);
 
627
                                RemoveFileItemFromList(pFileItem);
 
628
                        }
 
629
                        delete pItem;
 
630
                }
 
631
                else
 
632
                {
 
633
                        keepChildren.push_back(pItem);
 
634
                        m_visibleOffspring++;
 
635
                        m_visibleOffspring += pItem->GetChildrenCount(true);
 
636
                }
 
637
        }
 
638
        m_children = keepChildren;
 
639
 
 
640
        CQueueItem* parent = GetParent();
 
641
        while (parent)
 
642
        {
 
643
                parent->m_visibleOffspring -= oldVisibleOffspring - m_visibleOffspring;
 
644
                parent = parent->GetParent();
 
645
        }
 
646
 
 
647
        return m_children.empty();
 
648
}
 
649
 
 
650
void CServerItem::DetachChildren()
 
651
{
 
652
        wxASSERT(!m_activeCount);
 
653
 
 
654
        m_children.clear();
 
655
        m_visibleOffspring = 0;
 
656
        m_maxCachedIndex = -1;
 
657
 
 
658
        for (int i = 0; i < 2; i++)
 
659
                for (int j = 0; j < PRIORITY_COUNT; j++)
 
660
                        m_fileList[i][j].clear();
 
661
}
 
662
 
 
663
void CServerItem::SetPriority(enum QueuePriority priority)
 
664
{
 
665
        std::vector<CQueueItem*>::iterator iter;
 
666
        for (iter = m_children.begin(); iter != m_children.end(); iter++)
 
667
        {
 
668
                if ((*iter)->GetType() == QueueItemType_File)
 
669
                        ((CFileItem*)(*iter))->SetPriorityRaw(priority);
 
670
                else
 
671
                        (*iter)->SetPriority(priority);
 
672
        }
 
673
 
 
674
        for (int i = 0; i < 2; i++)
 
675
                for (int j = 0; j < PRIORITY_COUNT; j++)
 
676
                        if (j != priority)
 
677
                                m_fileList[i][priority].splice(m_fileList[i][priority].end(), m_fileList[i][j]);
 
678
}
 
679
 
 
680
void CServerItem::SetChildPriority(CFileItem* pItem, enum QueuePriority oldPriority, enum QueuePriority newPriority)
 
681
{
 
682
        int i = pItem->Queued() ? 0 : 1;
 
683
 
 
684
        for (std::list<CFileItem*>::iterator iter = m_fileList[i][oldPriority].begin(); iter != m_fileList[i][oldPriority].end(); iter++)
 
685
        {
 
686
                if (*iter != pItem)
 
687
                        continue;
 
688
 
 
689
                m_fileList[i][oldPriority].erase(iter);
 
690
                m_fileList[i][newPriority].push_back(pItem);
 
691
                return;
 
692
        }
 
693
 
 
694
        wxFAIL;
 
695
}
 
696
 
 
697
CFolderScanItem::CFolderScanItem(CServerItem* parent, bool queued, bool download, const wxString& localPath, const CServerPath& remotePath)
 
698
{
 
699
        m_parent = parent;
 
700
 
 
701
        m_download = download;
 
702
        m_localPath = localPath;
 
703
        m_remotePath = remotePath;
 
704
        m_queued = queued;
 
705
        m_remove = false;
 
706
        m_active = false;
 
707
        m_count = 0;
 
708
        t_dirPair pair;
 
709
        pair.localPath = localPath.c_str();
 
710
        pair.remotePath.SetSafePath(remotePath.GetSafePath().c_str());
 
711
        m_dirsToCheck.push_back(pair);
 
712
 
 
713
        m_defaultFileExistsAction = -1;
 
714
}
 
715
 
 
716
bool CFolderScanItem::TryRemoveAll()
 
717
{
 
718
        if (!m_active)
 
719
                return true;
 
720
 
 
721
        m_remove = true;
 
722
        return false;
 
723
}
 
724
 
 
725
// --------------
 
726
// CQueueViewBase
 
727
// --------------
 
728
 
 
729
BEGIN_EVENT_TABLE(CQueueViewBase, wxListCtrl)
 
730
EVT_ERASE_BACKGROUND(CQueueViewBase::OnEraseBackground)
 
731
EVT_NAVIGATION_KEY(CQueueViewBase::OnNavigationKey)
 
732
EVT_CHAR(CQueueViewBase::OnChar)
 
733
END_EVENT_TABLE()
 
734
 
 
735
CQueueViewBase::CQueueViewBase(CQueue* parent, int index, const wxString& title)
 
736
        : wxListCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN | wxLC_REPORT | wxLC_VIRTUAL | wxSUNKEN_BORDER | wxTAB_TRAVERSAL),
 
737
          m_pageIndex(index), m_title(title)
 
738
{
 
739
        m_pQueue = parent;
 
740
        m_insertionStart = -1;
 
741
        m_insertionCount = 0;
 
742
        m_itemCount = 0;
 
743
        m_allowBackgroundErase = true;
 
744
 
 
745
        m_fileCount = 0;
 
746
        m_folderScanCount = 0;
 
747
        m_fileCountChanged = false;
 
748
        m_folderScanCountChanged = false;
 
749
 
 
750
        // Create and assign the image list for the queue
 
751
        wxImageList* pImageList = new wxImageList(16, 16);
 
752
 
 
753
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_SERVER"),  wxART_OTHER, wxSize(16, 16)));
 
754
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_FILE"),  wxART_OTHER, wxSize(16, 16)));
 
755
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_FOLDERCLOSED"),  wxART_OTHER, wxSize(16, 16)));
 
756
        pImageList->Add(wxArtProvider::GetBitmap(_T("ART_FOLDER"),  wxART_OTHER, wxSize(16, 16)));
 
757
 
 
758
        AssignImageList(pImageList, wxIMAGE_LIST_SMALL);
 
759
}
 
760
 
 
761
CQueueViewBase::~CQueueViewBase()
 
762
{
 
763
        for (std::vector<CServerItem*>::iterator iter = m_serverList.begin(); iter != m_serverList.end(); iter++)
 
764
                delete *iter;
 
765
}
 
766
 
 
767
CQueueItem* CQueueViewBase::GetQueueItem(unsigned int item)
 
768
{
 
769
        std::vector<CServerItem*>::iterator iter;
 
770
        for (iter = m_serverList.begin(); iter != m_serverList.end(); iter++)
 
771
        {
 
772
                if (!item)
 
773
                        return *iter;
 
774
 
 
775
                unsigned int count = (*iter)->GetChildrenCount(true);
 
776
                if (item > count)
 
777
                {
 
778
                        item -= count + 1;
 
779
                        continue;
 
780
                }
 
781
 
 
782
                return (*iter)->GetChild(item - 1);
 
783
        }
 
784
        return 0;
 
785
}
 
786
 
 
787
int CQueueViewBase::GetItemIndex(const CQueueItem* item)
 
788
{
 
789
        const CQueueItem* pTopLevelItem = item->GetTopLevelItem();
 
790
 
 
791
        int index = 0;
 
792
        for (std::vector<CServerItem*>::const_iterator iter = m_serverList.begin(); iter != m_serverList.end(); iter++)
 
793
        {
 
794
                if (pTopLevelItem == *iter)
 
795
                        break;
 
796
 
 
797
                index += (*iter)->GetChildrenCount(true) + 1;
 
798
        }
 
799
 
 
800
        return index + item->GetItemIndex();
 
801
}
 
802
 
 
803
void CQueueViewBase::OnEraseBackground(wxEraseEvent& event)
 
804
{
 
805
        if (m_allowBackgroundErase)
 
806
                event.Skip();
 
807
}
 
808
 
 
809
wxString CQueueViewBase::OnGetItemText(long item, long column) const
 
810
{
 
811
        CQueueViewBase* pThis = const_cast<CQueueViewBase*>(this);
 
812
 
 
813
        CQueueItem* pItem = pThis->GetQueueItem(item);
 
814
        if (!pItem)
 
815
                return _T("");
 
816
 
 
817
        switch (pItem->GetType())
 
818
        {
 
819
        case QueueItemType_Server:
 
820
                {
 
821
                        CServerItem* pServerItem = reinterpret_cast<CServerItem*>(pItem);
 
822
                        if (!column)
 
823
                                return pServerItem->GetName();
 
824
                }
 
825
                break;
 
826
        case QueueItemType_File:
 
827
                {
 
828
                        CFileItem* pFileItem = reinterpret_cast<CFileItem*>(pItem);
 
829
                        switch (column)
 
830
                        {
 
831
                        case 0:
 
832
                                return pFileItem->GetIndent() + pFileItem->GetLocalFile();
 
833
                        case 1:
 
834
                                if (pFileItem->Download())
 
835
                                        if (pFileItem->Queued())
 
836
                                                return _T("<--");
 
837
                                        else
 
838
                                                return _T("<<--");
 
839
                                else
 
840
                                        if (pFileItem->Queued())
 
841
                                                return _T("-->");
 
842
                                        else
 
843
                                                return _T("-->>");
 
844
                                break;
 
845
                        case 2:
 
846
                                return pFileItem->GetRemotePath().FormatFilename(pFileItem->GetRemoteFile());
 
847
                        case 3:
 
848
                                {
 
849
                                        wxLongLong size = pFileItem->GetSize();
 
850
                                        if (size >= 0)
 
851
                                                return size.ToString();
 
852
                                        else
 
853
                                                return _T("?");
 
854
                                }
 
855
                        case 4:
 
856
                                switch (pFileItem->GetPriority())
 
857
                                {
 
858
                                case 0:
 
859
                                        return _("Lowest");
 
860
                                case 1:
 
861
                                        return _("Low");
 
862
                                default:
 
863
                                case 2:
 
864
                                        return _("Normal");
 
865
                                case 3:
 
866
                                        return _("High");
 
867
                                case 4:
 
868
                                        return _("Highest");
 
869
                                }
 
870
                                break;
 
871
                        case 5:
 
872
                                return pFileItem->m_statusMessage;
 
873
                        default:
 
874
                                break;
 
875
                        }
 
876
                }
 
877
                break;
 
878
        case QueueItemType_FolderScan:
 
879
                {
 
880
                        CFolderScanItem* pFolderItem = reinterpret_cast<CFolderScanItem*>(pItem);
 
881
                        switch (column)
 
882
                        {
 
883
                        case 0:
 
884
                                return _T("  ") + pFolderItem->GetLocalPath();
 
885
                        case 1:
 
886
                                if (pFolderItem->Download())
 
887
                                        if (pFolderItem->Queued())
 
888
                                                return _T("<--");
 
889
                                        else
 
890
                                                return _T("<<--");
 
891
                                else
 
892
                                        if (pFolderItem->Queued())
 
893
                                                return _T("-->");
 
894
                                        else
 
895
                                                return _T("-->>");
 
896
                                break;
 
897
                        case 2:
 
898
                                return pFolderItem->GetRemotePath().GetPath();
 
899
                        case 5:
 
900
                                return pFolderItem->m_statusMessage;
 
901
                        default:
 
902
                                break;
 
903
                        }
 
904
                }
 
905
                break;
 
906
        case QueueItemType_Folder:
 
907
                {
 
908
                        CFileItem* pFolderItem = reinterpret_cast<CFolderItem*>(pItem);
 
909
                        switch (column)
 
910
                        {
 
911
                        case 0:
 
912
                                if (pFolderItem->Download())
 
913
                                        return pFolderItem->GetIndent() + pFolderItem->GetLocalFile();
 
914
                                break;
 
915
                        case 1:
 
916
                                if (pFolderItem->Download())
 
917
                                        if (pFolderItem->Queued())
 
918
                                                return _T("<--");
 
919
                                        else
 
920
                                                return _T("<<--");
 
921
                                else
 
922
                                        if (pFolderItem->Queued())
 
923
                                                return _T("-->");
 
924
                                        else
 
925
                                                return _T("-->>");
 
926
                                break;
 
927
                        case 2:
 
928
                                if (!pFolderItem->Download())
 
929
                                {
 
930
                                        if (pFolderItem->GetRemoteFile() == _T(""))
 
931
                                                return pFolderItem->GetRemotePath().GetPath();
 
932
                                        else
 
933
                                                return pFolderItem->GetRemotePath().FormatFilename(pFolderItem->GetRemoteFile());
 
934
                                }
 
935
                                break;
 
936
                        case 4:
 
937
                                switch (pFolderItem->GetPriority())
 
938
                                {
 
939
                                case 0:
 
940
                                        return _("Lowest");
 
941
                                case 1:
 
942
                                        return _("Low");
 
943
                                default:
 
944
                                case 2:
 
945
                                        return _("Normal");
 
946
                                case 3:
 
947
                                        return _("High");
 
948
                                case 4:
 
949
                                        return _("Highest");
 
950
                                }
 
951
                                break;
 
952
                        case 5:
 
953
                                return pFolderItem->m_statusMessage;
 
954
                        default:
 
955
                                break;
 
956
                        }
 
957
                }
 
958
                break;
 
959
        default:
 
960
                break;
 
961
        }
 
962
 
 
963
        return _T("");
 
964
}
 
965
 
 
966
int CQueueViewBase::OnGetItemImage(long item) const
 
967
{
 
968
        CQueueViewBase* pThis = const_cast<CQueueViewBase*>(this);
 
969
 
 
970
        CQueueItem* pItem = pThis->GetQueueItem(item);
 
971
        if (!pItem)
 
972
                return -1;
 
973
 
 
974
        switch (pItem->GetType())
 
975
        {
 
976
        case QueueItemType_Server:
 
977
                return 0;
 
978
        case QueueItemType_File:
 
979
                return 1;
 
980
        case QueueItemType_FolderScan:
 
981
        case QueueItemType_Folder:
 
982
                        return 3;
 
983
        default:
 
984
                return -1;
 
985
        }
 
986
 
 
987
        return -1;
 
988
}
 
989
 
 
990
void CQueueViewBase::UpdateSelections_ItemAdded(int added)
 
991
{
 
992
        // This is the fastest algorithm I can think of to move all
 
993
        // selections. Though worst case is still O(n), as with every algorithm to
 
994
        // move selections.
 
995
 
 
996
        // Go through all items, keep record of the previous selected item
 
997
        int item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
998
        while (item != -1 && item < added)
 
999
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1000
 
 
1001
        int prevItem = -1;
 
1002
        while (item != -1)
 
1003
        {
 
1004
                if (prevItem != -1)
 
1005
                {
 
1006
                        if (prevItem + 1 != item)
 
1007
                        {
 
1008
                                // Previous selected item was not the direct predecessor
 
1009
                                // That means we have to select the successor of prevItem
 
1010
                                // and unselect current item
 
1011
                                SetItemState(prevItem + 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1012
                                SetItemState(item, 0, wxLIST_STATE_SELECTED);
 
1013
                        }
 
1014
                }
 
1015
                else
 
1016
                {
 
1017
                        // First selected item, no predecessor yet. We have to unselect
 
1018
                        SetItemState(item, 0, wxLIST_STATE_SELECTED);
 
1019
                }
 
1020
                prevItem = item;
 
1021
 
 
1022
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1023
        }
 
1024
        if (prevItem != -1 && prevItem < m_itemCount - 1)
 
1025
        {
 
1026
                // Move the very last selected item
 
1027
                SetItemState(prevItem + 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1028
        }
 
1029
 
 
1030
        SetItemState(added, 0, wxLIST_STATE_SELECTED);
 
1031
}
 
1032
 
 
1033
void CQueueViewBase::UpdateSelections_ItemRangeAdded(int added, int count)
 
1034
{
 
1035
        std::list<int> itemsToSelect;
 
1036
 
 
1037
        // Go through all selected items
 
1038
        int item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1039
        while (item != -1 && item < added)
 
1040
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1041
 
 
1042
        while (item != -1)
 
1043
        {
 
1044
                // Select new items preceeding to current one
 
1045
                while (!itemsToSelect.empty() && itemsToSelect.front() < item)
 
1046
                {
 
1047
                        SetItemState(itemsToSelect.front(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1048
                        itemsToSelect.pop_front();
 
1049
                }
 
1050
                if (itemsToSelect.empty())
 
1051
                        SetItemState(item, 0, wxLIST_STATE_SELECTED);
 
1052
                else if (itemsToSelect.front() == item)
 
1053
                        itemsToSelect.pop_front();
 
1054
 
 
1055
                itemsToSelect.push_back(item + count);
 
1056
 
 
1057
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1058
        }
 
1059
        for (std::list<int>::const_iterator iter = itemsToSelect.begin(); iter != itemsToSelect.end(); iter++)
 
1060
                SetItemState(*iter, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1061
}
 
1062
 
 
1063
void CQueueViewBase::UpdateSelections_ItemRemoved(int removed)
 
1064
{
 
1065
        SetItemState(removed, 0, wxLIST_STATE_SELECTED);
 
1066
 
 
1067
        int prevItem = -1;
 
1068
        int item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1069
        while (item != -1 && item < removed)
 
1070
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1071
 
 
1072
        while (item != -1)
 
1073
        {
 
1074
                if (prevItem != -1)
 
1075
                {
 
1076
                        if (prevItem + 1 != item)
 
1077
                        {
 
1078
                                // Previous selected item was not the direct predecessor
 
1079
                                // That means we have to select our predecessor and unselect
 
1080
                                // prevItem
 
1081
                                SetItemState(prevItem, 0, wxLIST_STATE_SELECTED);
 
1082
                                SetItemState(item - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1083
                        }
 
1084
                }
 
1085
                else
 
1086
                {
 
1087
                        // First selected item, no predecessor yet. We have to unselect
 
1088
                        SetItemState(item - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1089
                }
 
1090
                prevItem = item;
 
1091
 
 
1092
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1093
        }
 
1094
        if (prevItem != -1)
 
1095
        {
 
1096
                SetItemState(prevItem, 0, wxLIST_STATE_SELECTED);
 
1097
        }
 
1098
}
 
1099
 
 
1100
void CQueueViewBase::UpdateSelections_ItemRangeRemoved(int removed, int count)
 
1101
{
 
1102
        SetItemState(removed, 0, wxLIST_STATE_SELECTED);
 
1103
 
 
1104
        std::list<int> itemsToUnselect;
 
1105
 
 
1106
        int item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1107
        while (item != -1 && item < removed)
 
1108
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1109
 
 
1110
        while (item != -1)
 
1111
        {
 
1112
                // Unselect new items preceeding to current one
 
1113
                while (!itemsToUnselect.empty() && itemsToUnselect.front() < item - count)
 
1114
                {
 
1115
                        SetItemState(itemsToUnselect.front(), 0, wxLIST_STATE_SELECTED);
 
1116
                        itemsToUnselect.pop_front();
 
1117
                }
 
1118
 
 
1119
                if (itemsToUnselect.empty())
 
1120
                        SetItemState(item - count, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1121
                else if (itemsToUnselect.front() == item - count)
 
1122
                        itemsToUnselect.pop_front();
 
1123
                else
 
1124
                        SetItemState(item - count, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
 
1125
 
 
1126
                itemsToUnselect.push_back(item);
 
1127
 
 
1128
                item = GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
 
1129
        }
 
1130
        for (std::list<int>::const_iterator iter = itemsToUnselect.begin(); iter != itemsToUnselect.end(); iter++)
 
1131
                SetItemState(*iter, 0, wxLIST_STATE_SELECTED);
 
1132
}
 
1133
 
 
1134
void CQueueViewBase::CreateColumns(const wxString& lastColumnName)
 
1135
{
 
1136
        InsertColumn(0, _("Server / Local file"), wxLIST_FORMAT_LEFT, 150);
 
1137
        InsertColumn(1, _("Direction"), wxLIST_FORMAT_CENTER, 60);
 
1138
        InsertColumn(2, _("Remote file"), wxLIST_FORMAT_LEFT, 150);
 
1139
        InsertColumn(3, _("Size"), wxLIST_FORMAT_RIGHT, 70);
 
1140
        InsertColumn(4, _("Priority"), wxLIST_FORMAT_LEFT, 60);
 
1141
        if (lastColumnName != _T(""))
 
1142
                InsertColumn(5, lastColumnName, wxLIST_FORMAT_LEFT, 150);
 
1143
}
 
1144
 
 
1145
CServerItem* CQueueViewBase::GetServerItem(const CServer& server)
 
1146
{
 
1147
        for (std::vector<CServerItem*>::iterator iter = m_serverList.begin(); iter != m_serverList.end(); iter++)
 
1148
        {
 
1149
                if ((*iter)->GetServer() == server)
 
1150
                        return *iter;
 
1151
        }
 
1152
        return NULL;
 
1153
}
 
1154
 
 
1155
CServerItem* CQueueViewBase::CreateServerItem(const CServer& server)
 
1156
{
 
1157
        CServerItem* pItem = GetServerItem(server);
 
1158
 
 
1159
        if (!pItem)
 
1160
        {
 
1161
                pItem = new CServerItem(server);
 
1162
                m_serverList.push_back(pItem);
 
1163
                m_itemCount++;
 
1164
 
 
1165
                wxASSERT(m_insertionStart == -1);
 
1166
                wxASSERT(m_insertionCount == 0);
 
1167
 
 
1168
                m_insertionStart = GetItemIndex(pItem);
 
1169
                m_insertionCount = 1;
 
1170
        }
 
1171
 
 
1172
        return pItem;
 
1173
}
 
1174
 
 
1175
void CQueueViewBase::CommitChanges()
 
1176
{
 
1177
        SetItemCount(m_itemCount);
 
1178
 
 
1179
        if (m_insertionStart != -1)
 
1180
        {
 
1181
                wxASSERT(m_insertionCount != 0);
 
1182
                if (m_insertionCount == 1)
 
1183
                        UpdateSelections_ItemAdded(m_insertionStart);
 
1184
                else
 
1185
                        UpdateSelections_ItemRangeAdded(m_insertionStart, m_insertionCount);
 
1186
 
 
1187
                m_insertionStart = -1;
 
1188
                m_insertionCount = 0;
 
1189
        }
 
1190
 
 
1191
        if (m_fileCountChanged || m_folderScanCountChanged)
 
1192
                DisplayNumberQueuedFiles();
 
1193
}
 
1194
 
 
1195
void CQueueViewBase::DisplayNumberQueuedFiles()
 
1196
{
 
1197
        wxString str;
 
1198
        if (m_fileCount > 0)
 
1199
        {
 
1200
                if (!m_folderScanCount)
 
1201
                        str.Printf(m_title + _T(" (%d)"), m_fileCount);
 
1202
                else
 
1203
                        str.Printf(m_title + _T(" (%d+)"), m_fileCount);
 
1204
        }
 
1205
        else
 
1206
        {
 
1207
                if (m_folderScanCount)
 
1208
                        str.Printf(m_title + _T(" (0+)"), m_fileCount);
 
1209
                else
 
1210
                        str = m_title;
 
1211
        }
 
1212
        m_pQueue->SetPageText(m_pageIndex, str);
 
1213
 
 
1214
        m_fileCountChanged = false;
 
1215
        m_folderScanCountChanged = false;
 
1216
}
 
1217
 
 
1218
void CQueueViewBase::InsertItem(CServerItem* pServerItem, CQueueItem* pItem)
 
1219
{
 
1220
        pServerItem->AddChild(pItem);
 
1221
        m_itemCount++;
 
1222
 
 
1223
        if (m_insertionStart == -1)
 
1224
                m_insertionStart = GetItemIndex(pItem);
 
1225
        m_insertionCount++;
 
1226
 
 
1227
        if (pItem->GetType() == QueueItemType_File || pItem->GetType() == QueueItemType_Folder)
 
1228
        {
 
1229
                m_fileCount++;
 
1230
                m_fileCountChanged = true;
 
1231
        }
 
1232
        else if (pItem->GetType() == QueueItemType_FolderScan)
 
1233
        {
 
1234
                m_folderScanCount++;
 
1235
                m_folderScanCountChanged = true;
 
1236
        }
 
1237
}
 
1238
 
 
1239
bool CQueueViewBase::RemoveItem(CQueueItem* pItem, bool destroy, bool updateItemCount /*=true*/, bool updateSelections /*=true*/)
 
1240
{
 
1241
        if (pItem->GetType() == QueueItemType_File || pItem->GetType() == QueueItemType_Folder)
 
1242
        {
 
1243
                wxASSERT(m_fileCount > 0);
 
1244
                m_fileCount--;
 
1245
                m_fileCountChanged = true;
 
1246
        }
 
1247
        else if (pItem->GetType() == QueueItemType_FolderScan)
 
1248
        {
 
1249
                wxASSERT(m_folderScanCount > 0);
 
1250
                m_folderScanCount--;
 
1251
                m_folderScanCountChanged = true;
 
1252
                
 
1253
        }
 
1254
 
 
1255
        int index = 0;
 
1256
        if (updateSelections)
 
1257
                index = GetItemIndex(pItem);
 
1258
        
 
1259
        CQueueItem* topLevelItem = pItem->GetTopLevelItem();
 
1260
 
 
1261
        int count = topLevelItem->GetChildrenCount(true);
 
1262
        topLevelItem->RemoveChild(pItem, destroy);
 
1263
 
 
1264
        bool didRemoveParent;
 
1265
 
 
1266
        int oldCount = m_itemCount;
 
1267
        if (!topLevelItem->GetChild(0))
 
1268
        {
 
1269
                std::vector<CServerItem*>::iterator iter;
 
1270
                for (iter = m_serverList.begin(); iter != m_serverList.end(); iter++)
 
1271
                {
 
1272
                        if (*iter == topLevelItem)
 
1273
                                break;
 
1274
                }
 
1275
                if (iter != m_serverList.end())
 
1276
                        m_serverList.erase(iter);
 
1277
 
 
1278
                UpdateSelections_ItemRangeRemoved(GetItemIndex(topLevelItem), count + 1);
 
1279
 
 
1280
                delete topLevelItem;
 
1281
 
 
1282
                m_itemCount -= count + 1;
 
1283
                if (updateItemCount)
 
1284
                        SetItemCount(m_itemCount);
 
1285
 
 
1286
                didRemoveParent = true;
 
1287
        }
 
1288
        else
 
1289
        {
 
1290
                count -= topLevelItem->GetChildrenCount(true);
 
1291
 
 
1292
                if (updateSelections)
 
1293
                        UpdateSelections_ItemRangeRemoved(index, count);
 
1294
 
 
1295
                m_itemCount -= count;
 
1296
                if (updateItemCount)
 
1297
                        SetItemCount(m_itemCount);
 
1298
 
 
1299
                didRemoveParent = false;
 
1300
        }
 
1301
 
 
1302
        if (updateItemCount)
 
1303
        {
 
1304
                if (m_fileCountChanged || m_folderScanCountChanged)
 
1305
                        DisplayNumberQueuedFiles();
 
1306
                if (oldCount > m_itemCount)
 
1307
                {
 
1308
                        bool eraseBackground = GetTopItem() + GetCountPerPage() + 1 >= m_itemCount;
 
1309
                        Refresh(eraseBackground);
 
1310
                        if (eraseBackground)
 
1311
                                Update();
 
1312
                }
 
1313
        }
 
1314
 
 
1315
        return didRemoveParent;
 
1316
}
 
1317
 
 
1318
void CQueueViewBase::RefreshItem(const CQueueItem* pItem)
 
1319
{
 
1320
        wxASSERT(pItem);
 
1321
        int index = GetItemIndex(pItem);
 
1322
 
 
1323
        wxListCtrl::RefreshItem(index);
 
1324
}
 
1325
 
 
1326
void CQueueViewBase::OnNavigationKey(wxNavigationKeyEvent& event)
 
1327
{
 
1328
        event.SetEventObject(m_pQueue);
 
1329
        m_pQueue->ProcessEvent(event);
 
1330
}
 
1331
 
 
1332
void CQueueViewBase::OnChar(wxKeyEvent& event)
 
1333
{
 
1334
        const int code = event.GetKeyCode();
 
1335
        if (code != WXK_LEFT && code != WXK_RIGHT)
 
1336
        {
 
1337
                event.Skip();
 
1338
                return;
 
1339
        }
 
1340
 
 
1341
        int selection = m_pQueue->GetSelection();
 
1342
        if (selection > 0 && code == WXK_LEFT)
 
1343
                selection--;
 
1344
        else if (selection < (int)m_pQueue->GetPageCount() - 1 && code == WXK_RIGHT)
 
1345
                selection++;
 
1346
        else
 
1347
                return;
 
1348
 
 
1349
        m_pQueue->SetSelection(selection);
 
1350
}
 
1351
 
 
1352
// ------
 
1353
// CQueue
 
1354
// ------
 
1355
 
 
1356
CQueue::CQueue(wxWindow* parent, CMainFrame *pMainFrame, CAsyncRequestQueue *pAsyncRequestQueue)
 
1357
{
 
1358
        Create(parent, -1, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | wxAUI_NB_BOTTOM);
 
1359
        SetExArtProvider();
 
1360
 
 
1361
        m_pQueueView = new CQueueView(this, 0, pMainFrame, pAsyncRequestQueue);
 
1362
        AddPage(m_pQueueView, m_pQueueView->GetTitle());
 
1363
 
 
1364
        m_pQueueView_Failed = new CQueueViewFailed(this, 1);
 
1365
        AddPage(m_pQueueView_Failed, m_pQueueView_Failed->GetTitle());
 
1366
        m_pQueueView_Successful = new CQueueViewSuccessful(this, 2);
 
1367
        AddPage(m_pQueueView_Successful, m_pQueueView_Successful->GetTitle());
 
1368
 
 
1369
        RemoveExtraBorders();
 
1370
 
 
1371
        m_pQueueView->LoadQueue();
 
1372
}
 
1373
 
 
1374
void CQueue::SetFocus()
 
1375
{
 
1376
        GetPage(GetSelection())->SetFocus();
 
1377
}