utilities/downloadmanager/src/sequentialdownloadmanager.cpp
changeset 16 3c88a81ff781
equal deleted inserted replaced
14:6aeb7a756187 16:3c88a81ff781
       
     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 }