|
1 /** |
|
2 This file is part of CWRT package ** |
|
3 |
|
4 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** |
|
5 |
|
6 This program is free software: you can redistribute it and/or modify |
|
7 it under the terms of the GNU (Lesser) General Public License as |
|
8 published by the Free Software Foundation, version 2.1 of the License. |
|
9 This program is distributed in the hope that it will be useful, but |
|
10 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 (Lesser) General Public License for more details. You should have |
|
13 received a copy of the GNU (Lesser) General Public License along |
|
14 with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 */ |
|
16 |
|
17 #include "downloadmanager.h" |
|
18 #include "download.h" |
|
19 #include "sequentialdownloadmanager.h" |
|
20 #include "downloadevent.h" |
|
21 #include "clientdownload.h" |
|
22 |
|
23 class SequentialDownloadManagerPrivate |
|
24 { |
|
25 //declare public implementation |
|
26 DM_DECLARE_PUBLIC(SequentialDownloadManager); |
|
27 public: |
|
28 SequentialDownloadManagerPrivate(); |
|
29 ~SequentialDownloadManagerPrivate(); |
|
30 |
|
31 QList<Download*> m_createdDownloads; // list of downloads which have been created by the client and owns them |
|
32 QQueue<Download*> m_downloadsQueue; // queue of downloads scheduled for downloading and owns them |
|
33 QList<Download*> m_completedDownloads; // list of downloads which have been completed and owns them |
|
34 QList<Download*> m_failedDownloads; // list of failed downloads |
|
35 QList<Download*> m_totalDownloads; // total of all the above downloads, but this doesnt own downloads |
|
36 }; |
|
37 |
|
38 SequentialDownloadManagerPrivate::SequentialDownloadManagerPrivate() |
|
39 { } |
|
40 |
|
41 SequentialDownloadManagerPrivate::~SequentialDownloadManagerPrivate() |
|
42 { |
|
43 int createdSize = m_createdDownloads.size(); |
|
44 for (int i = 0; i < createdSize; i++) |
|
45 delete m_createdDownloads[i]; |
|
46 m_createdDownloads.clear(); |
|
47 |
|
48 int completedSize = m_completedDownloads.size(); |
|
49 for (int i = 0; i < completedSize; i++) |
|
50 delete m_completedDownloads[i]; |
|
51 m_completedDownloads.clear(); |
|
52 |
|
53 int size = m_downloadsQueue.size(); |
|
54 for (int i = 0; i < size; i++) { |
|
55 DownloadState state = (DownloadState)((m_downloadsQueue[i]->getAttribute(DlDownloadState)).toInt()); |
|
56 if (state == DlInprogress) { |
|
57 // pause the download if it is in progress |
|
58 m_downloadsQueue[i]->pause(); |
|
59 } else if (state == DlFailed) { |
|
60 // cancel the download if it has failed |
|
61 m_downloadsQueue[i]->cancel(); |
|
62 } |
|
63 delete (m_downloadsQueue[i]); |
|
64 } |
|
65 m_downloadsQueue.clear(); |
|
66 } |
|
67 |
|
68 /* |
|
69 constructor |
|
70 */ |
|
71 SequentialDownloadManager::SequentialDownloadManager() |
|
72 { |
|
73 DM_INITIALIZE(SequentialDownloadManager); |
|
74 } |
|
75 |
|
76 /* |
|
77 destructor |
|
78 */ |
|
79 SequentialDownloadManager::~SequentialDownloadManager() |
|
80 { |
|
81 DM_UNINITIALIZE(SequentialDownloadManager); |
|
82 } |
|
83 |
|
84 /* |
|
85 returns all the current downloads |
|
86 */ |
|
87 QList<Download*>& SequentialDownloadManager::currentDownloads() |
|
88 { |
|
89 DM_PRIVATE(SequentialDownloadManager); |
|
90 priv->m_totalDownloads.clear(); |
|
91 for (int i = 0; i < priv->m_completedDownloads.size(); ++i) |
|
92 priv->m_totalDownloads.append(priv->m_completedDownloads[i]); |
|
93 for (int i = 0; i < priv->m_downloadsQueue.size(); ++i) |
|
94 priv->m_totalDownloads.append(priv->m_downloadsQueue[i]); |
|
95 for (int i = 0; i < priv->m_createdDownloads.size(); ++i) |
|
96 priv->m_totalDownloads.append(priv->m_createdDownloads[i]); |
|
97 for (int i = 0; i < priv->m_failedDownloads.size(); ++i) |
|
98 priv->m_totalDownloads.append(priv->m_failedDownloads[i]); |
|
99 return priv->m_totalDownloads; |
|
100 } |
|
101 |
|
102 /* |
|
103 finds a download provided id if exists |
|
104 \a id indicates identifier for download |
|
105 */ |
|
106 Download* SequentialDownloadManager::findDownload(int dlId) |
|
107 { |
|
108 DM_PRIVATE(SequentialDownloadManager); |
|
109 for (int i = 0; i < priv->m_completedDownloads.size(); ++i) { |
|
110 if (priv->m_completedDownloads[i]->id() == dlId) |
|
111 return priv->m_completedDownloads[i]; |
|
112 } |
|
113 for (int i = 0; i < priv->m_downloadsQueue.size(); ++i) { |
|
114 if (priv->m_downloadsQueue[i]->id() == dlId) |
|
115 return priv->m_downloadsQueue[i]; |
|
116 } |
|
117 for (int i = 0; i < priv->m_createdDownloads.size(); ++i) { |
|
118 if (priv->m_createdDownloads[i]->id() == dlId) |
|
119 return priv->m_createdDownloads[i]; |
|
120 } |
|
121 return 0; |
|
122 } |
|
123 |
|
124 /* |
|
125 cancels all the downloads |
|
126 */ |
|
127 void SequentialDownloadManager::removeAll() |
|
128 { |
|
129 DM_PRIVATE(SequentialDownloadManager); |
|
130 //traverse the list and delete each download in the list |
|
131 for(int i = 0; i < priv->m_downloadsQueue.count(); ) { |
|
132 // cancel the download |
|
133 priv->m_downloadsQueue[0]->cancel(); |
|
134 delete (priv->m_downloadsQueue[0]); |
|
135 priv->m_downloadsQueue.removeAt(0); |
|
136 } |
|
137 priv->m_downloadsQueue.clear(); |
|
138 |
|
139 int createdDownloadsCount = priv->m_createdDownloads.count(); |
|
140 //traverse the list and delete each download in the list |
|
141 for(int i = 0; i < createdDownloadsCount; i++) |
|
142 delete (priv->m_createdDownloads[i]); |
|
143 priv->m_createdDownloads.clear(); |
|
144 |
|
145 int completedDownloadsCount = priv->m_completedDownloads.count(); |
|
146 //traverse the list and delete each download in the list |
|
147 for(int i = 0; i < completedDownloadsCount; i++) |
|
148 delete (priv->m_completedDownloads[i]); |
|
149 priv->m_completedDownloads.clear(); |
|
150 |
|
151 int failedDownloadsCount = priv->m_failedDownloads.count(); |
|
152 //traverse the list and delete each download in the list |
|
153 for(int i = 0; i < failedDownloadsCount; i++) |
|
154 delete (priv->m_failedDownloads[i]); |
|
155 priv->m_failedDownloads.clear(); |
|
156 } |
|
157 |
|
158 /* |
|
159 cancels and removes the download |
|
160 \a dl indicates the download to be canceled and removed |
|
161 */ |
|
162 void SequentialDownloadManager::removeOne(Download *dl) |
|
163 { |
|
164 if(!dl) |
|
165 return; |
|
166 DM_PRIVATE(SequentialDownloadManager); |
|
167 if (currentDownloads().contains(dl)) { |
|
168 dl->cancel(); |
|
169 // download might be there in any of the following list |
|
170 priv->m_downloadsQueue.removeOne(dl); |
|
171 priv->m_createdDownloads.removeOne(dl); |
|
172 priv->m_completedDownloads.removeOne(dl); |
|
173 delete dl; |
|
174 dl = 0; |
|
175 } |
|
176 } |
|
177 |
|
178 /* |
|
179 pauses all the downloads which are in progress |
|
180 */ |
|
181 void SequentialDownloadManager::pauseAll() |
|
182 { |
|
183 DM_PRIVATE(SequentialDownloadManager); |
|
184 if (!priv->m_downloadsQueue.isEmpty()) { |
|
185 QQueue<Download*>::iterator i; |
|
186 i = priv->m_downloadsQueue.begin(); |
|
187 DownloadState state = (DownloadState)(((*i)->getAttribute(DlDownloadState)).toInt()); |
|
188 if ((state == DlInprogress || state == DlStarted)) |
|
189 dynamic_cast<ClientDownload*>(*i)->pauseDownload(); |
|
190 } |
|
191 } |
|
192 |
|
193 /* |
|
194 resumes all the downloads which are paused |
|
195 */ |
|
196 void SequentialDownloadManager::resumeAll() |
|
197 { |
|
198 DM_PRIVATE(SequentialDownloadManager); |
|
199 if (!priv->m_downloadsQueue.isEmpty()) { |
|
200 QQueue<Download*>::iterator i; |
|
201 i = priv->m_downloadsQueue.begin(); |
|
202 DownloadState state = (DownloadState)(((*i)->getAttribute(DlDownloadState)).toInt()); |
|
203 if (state == DlPaused) |
|
204 dynamic_cast<ClientDownload*>(*i)->resumeDownload(); |
|
205 } |
|
206 } |
|
207 |
|
208 void SequentialDownloadManager::addToSequentialDownload(Download* dl) |
|
209 { |
|
210 // Here the downloads are added first to a download list. When the downloads are in this list, |
|
211 // the client can set some attributes on the download. |
|
212 // Later the client has to explicitly call start() on the download after which, |
|
213 // download gets added to the downloadsQueue and the download starts. |
|
214 |
|
215 DM_PRIVATE(SequentialDownloadManager); |
|
216 |
|
217 // set the download type |
|
218 ClientDownload* download = dynamic_cast<ClientDownload*>(dl); |
|
219 if(download) |
|
220 download->attributes().insert(DlDownloadType, (int)Sequential); |
|
221 |
|
222 // if the download is already in queue but the prority has been changed |
|
223 if( findDownload(dl->id())) |
|
224 priv->m_createdDownloads.removeOne(dl); |
|
225 |
|
226 DownloadPriority priority = (DownloadPriority)(dl->getAttribute(DlPriority)).toInt(); |
|
227 if (priority == High) { |
|
228 QList<Download*>::iterator i; |
|
229 for (i = priv->m_createdDownloads.begin(); i != priv->m_createdDownloads.end(); i++) { |
|
230 if ((*i)->getAttribute(DlPriority).toInt() == Low) { |
|
231 priv->m_createdDownloads.insert(i, dl); |
|
232 return; |
|
233 } |
|
234 } |
|
235 priv->m_createdDownloads.insert(i, dl); // if no low priority download is found then just insert the high priority download |
|
236 } |
|
237 else |
|
238 priv->m_createdDownloads.append(dl); |
|
239 } |
|
240 |
|
241 void SequentialDownloadManager::addToDownloadQueue(Download* dl) |
|
242 { |
|
243 DM_PRIVATE(SequentialDownloadManager); |
|
244 priv->m_downloadsQueue.append(dl); |
|
245 } |
|
246 |
|
247 void SequentialDownloadManager::addToCompletedList(Download* dl) |
|
248 { |
|
249 DM_PRIVATE(SequentialDownloadManager); |
|
250 priv->m_completedDownloads.append(dl); |
|
251 } |
|
252 |
|
253 void SequentialDownloadManager::process(int dlId) |
|
254 { |
|
255 DM_PRIVATE(SequentialDownloadManager); |
|
256 // Start() has been called on a download present in the createdDownloads list. Move that download from the list to the queue |
|
257 ClientDownload* dl = dynamic_cast<ClientDownload*>(findDownload(dlId)); |
|
258 dl->registerEventReceiver(this); |
|
259 priv->m_createdDownloads.removeOne(dl); // Once start() is called on download, add it to downloadQueue & remove it from createdDownloads list |
|
260 if (priv->m_downloadsQueue.isEmpty()) { |
|
261 addToDownloadQueue(dl); |
|
262 dl->startDownload(); |
|
263 return; |
|
264 } |
|
265 DownloadPriority priority = (DownloadPriority)((dl->getAttribute(DlPriority)).toInt()); |
|
266 // checking for priority |
|
267 if (priority == High) { |
|
268 // Add the download before the first low priority item |
|
269 QQueue<Download*>::iterator i; |
|
270 for (i = priv->m_downloadsQueue.begin(); i != priv->m_downloadsQueue.end(); i++) { |
|
271 if ((*i)->getAttribute(DlPriority).toInt() == Low) { |
|
272 if (i == priv->m_downloadsQueue.begin()) { |
|
273 dynamic_cast<ClientDownload*>(*i)->pauseDownload(); |
|
274 priv->m_downloadsQueue.insert(i, dl); // low priority dl is in progress so pause it, insert the high priority dl and start it. |
|
275 dl->startDownload(); |
|
276 } |
|
277 else { |
|
278 // low priority download is present in the queue but it's not the first one as it is not yet started, |
|
279 // so there's already a high priority dl in progress. So this high priority dl should just be inserted into the queue. |
|
280 priv->m_downloadsQueue.insert(i, dl); |
|
281 } |
|
282 return; |
|
283 } |
|
284 } |
|
285 priv->m_downloadsQueue.insert(i, dl); // insert the high priority download if there are no low priority downloads in the queue |
|
286 } |
|
287 else |
|
288 addToDownloadQueue(dl); // If priority is low then just append to the queue. |
|
289 } |
|
290 |
|
291 bool SequentialDownloadManager::event(QEvent *event) |
|
292 { |
|
293 DM_PRIVATE(SequentialDownloadManager); |
|
294 DEventType type = (DEventType)event->type(); |
|
295 switch(type) { |
|
296 case Completed: |
|
297 { |
|
298 int dlId = ((DownloadEvent*)event)->getId(); |
|
299 ClientDownload *dl = dynamic_cast<ClientDownload*>(findDownload(dlId)); |
|
300 addToCompletedList(dl); |
|
301 // After adding the download to completed list, remove it from downloadQueue |
|
302 priv->m_downloadsQueue.removeOne(dl); |
|
303 startNext(); |
|
304 break; |
|
305 } |
|
306 case Error: |
|
307 { |
|
308 int dlId = ((DownloadEvent*)event)->getId(); |
|
309 ClientDownload *dl = dynamic_cast<ClientDownload*>(findDownload(dlId)); |
|
310 priv->m_failedDownloads.append(dl); |
|
311 priv->m_downloadsQueue.removeOne(dl); |
|
312 startNext(); |
|
313 break; |
|
314 } |
|
315 default: |
|
316 break; |
|
317 } |
|
318 return true; |
|
319 } |
|
320 |
|
321 void SequentialDownloadManager::startNext() |
|
322 { |
|
323 DM_PRIVATE(SequentialDownloadManager); |
|
324 QQueue<Download*>::iterator i; |
|
325 if (!priv->m_downloadsQueue.isEmpty()) { |
|
326 i = priv->m_downloadsQueue.begin(); |
|
327 DownloadState state = (DownloadState)(((*i)->getAttribute(DlDownloadState)).toInt()); |
|
328 if (state == DlPaused) |
|
329 (*i)->resume(); |
|
330 else |
|
331 dynamic_cast<ClientDownload*>(*i)->startDownload(); |
|
332 } |
|
333 } |
|
334 |
|
335 void SequentialDownloadManager::pauseDownload(int dlId) |
|
336 { |
|
337 DM_PRIVATE(SequentialDownloadManager); |
|
338 QQueue<Download*>::iterator i; |
|
339 if (!priv->m_downloadsQueue.isEmpty()) { |
|
340 i = priv->m_downloadsQueue.begin(); |
|
341 if (dlId == (*i)->id()) |
|
342 dynamic_cast<ClientDownload*>(*i)->pauseDownload(); |
|
343 } |
|
344 } |
|
345 |
|
346 void SequentialDownloadManager::resumeDownload(int dlId) |
|
347 { |
|
348 DM_PRIVATE(SequentialDownloadManager); |
|
349 QQueue<Download*>::iterator i; |
|
350 if (!priv->m_downloadsQueue.isEmpty()) { |
|
351 i = priv->m_downloadsQueue.begin(); |
|
352 if (dlId == (*i)->id()) |
|
353 dynamic_cast<ClientDownload*>(*i)->resumeDownload(); |
|
354 } |
|
355 } |
|
356 |
|
357 void SequentialDownloadManager::cancelDownload(int dlId) |
|
358 { |
|
359 DM_PRIVATE(SequentialDownloadManager); |
|
360 QQueue<Download*>::iterator i; |
|
361 if (!priv->m_downloadsQueue.isEmpty()) { |
|
362 i = priv->m_downloadsQueue.begin(); |
|
363 if (dlId == (*i)->id()) |
|
364 dynamic_cast<ClientDownload*>(*i)->cancelDownload(); |
|
365 } |
|
366 } |