File indexing completed on 2024-11-03 04:33:10
0001 /* This file is part of the KDE project 0002 0003 Copyright (C) 2005 Dario Massarin <nekkar@libero.it> 0004 Copyright (C) 2010 Matthias Fuchs <mat69@gmx.net> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 */ 0011 0012 #include "core/transfergroup.h" 0013 0014 #include "core/kget.h" 0015 #include "core/transfergrouphandler.h" 0016 0017 #include "kget_debug.h" 0018 #include <KIO/Global> 0019 0020 #include <QDomElement> 0021 0022 TransferGroup::TransferGroup(TransferTreeModel *model, Scheduler *parent, const QString &name) 0023 : JobQueue(parent) 0024 , m_model(model) 0025 , m_name(name) 0026 , m_totalSize(0) 0027 , m_downloadedSize(0) 0028 , m_uploadedSize(0) 0029 , m_percent(0) 0030 , m_downloadSpeed(0) 0031 , m_uploadSpeed(0) 0032 , m_downloadLimit(0) 0033 , m_uploadLimit(0) 0034 , m_visibleDownloadLimit(0) 0035 , m_visibleUploadLimit(0) 0036 , m_iconName("bookmark-new-list") 0037 , m_defaultFolder() 0038 { 0039 m_handler = new TransferGroupHandler(parent, this); 0040 } 0041 0042 TransferGroup::~TransferGroup() 0043 { 0044 } 0045 0046 int TransferGroup::downloadSpeed() 0047 { 0048 m_downloadSpeed = 0; 0049 foreach (Job *job, runningJobs()) { 0050 auto *transfer = static_cast<Transfer *>(job); 0051 if (transfer) 0052 m_downloadSpeed += transfer->downloadSpeed(); 0053 } 0054 return m_downloadSpeed; 0055 } 0056 0057 int TransferGroup::uploadSpeed() 0058 { 0059 m_uploadSpeed = 0; 0060 foreach (Job *job, runningJobs()) { 0061 auto *transfer = static_cast<Transfer *>(job); 0062 if (transfer) 0063 m_uploadSpeed += transfer->uploadSpeed(); 0064 } 0065 return m_uploadSpeed; 0066 } 0067 0068 bool TransferGroup::supportsSpeedLimits() 0069 { 0070 QList<Job *> jobs = runningJobs(); 0071 foreach (Job *job, jobs) { 0072 auto *transfer = static_cast<Transfer *>(job); 0073 if (!(transfer->capabilities() & Transfer::Cap_SpeedLimit)) { 0074 return false; 0075 } 0076 } 0077 0078 // empty jobs can't support a speed limit 0079 return !jobs.isEmpty(); 0080 } 0081 0082 void TransferGroup::setStatus(Status queueStatus) 0083 { 0084 JobQueue::setStatus(queueStatus); 0085 0086 m_handler->setGroupChange(Gc_Status, true); 0087 } 0088 0089 void TransferGroup::append(Transfer *transfer) 0090 { 0091 JobQueue::append(transfer); 0092 0093 calculateSpeedLimits(); 0094 } 0095 0096 void TransferGroup::append(const QList<Transfer *> &transfers) 0097 { 0098 QList<Job *> jobs; 0099 foreach (Transfer *transfer, transfers) { 0100 jobs << transfer; 0101 } 0102 JobQueue::append(jobs); 0103 0104 calculateSpeedLimits(); 0105 } 0106 0107 void TransferGroup::prepend(Transfer *transfer) 0108 { 0109 JobQueue::prepend(transfer); 0110 0111 calculateSpeedLimits(); 0112 } 0113 0114 void TransferGroup::insert(Transfer *transfer, Transfer *after) 0115 { 0116 JobQueue::insert(transfer, after); 0117 0118 calculateSpeedLimits(); 0119 } 0120 0121 void TransferGroup::remove(Transfer *transfer) 0122 { 0123 JobQueue::remove(transfer); 0124 0125 calculateSpeedLimits(); 0126 } 0127 0128 void TransferGroup::remove(const QList<Transfer *> &transfers) 0129 { 0130 QList<Job *> jobs; 0131 foreach (Transfer *transfer, transfers) { 0132 jobs << transfer; 0133 } 0134 JobQueue::remove(jobs); 0135 0136 calculateSpeedLimits(); 0137 } 0138 0139 void TransferGroup::move(Transfer *transfer, Transfer *after) 0140 { 0141 if (transfer == after) 0142 return; 0143 0144 JobQueue::move(transfer, after); 0145 } 0146 0147 Transfer *TransferGroup::findTransfer(const QUrl &src) 0148 { 0149 iterator it = begin(); 0150 iterator itEnd = end(); 0151 0152 for (; it != itEnd; ++it) { 0153 auto *t = (Transfer *)*it; 0154 if (t->source().url() == src.url()) 0155 return t; 0156 } 0157 return nullptr; 0158 } 0159 0160 Transfer *TransferGroup::findTransferByDestination(const QUrl &dest) 0161 { 0162 iterator it = begin(); 0163 iterator itEnd = end(); 0164 0165 for (; it != itEnd; ++it) { 0166 auto *t = (Transfer *)*it; 0167 if (t->dest().url() == dest.url()) { 0168 return t; 0169 } 0170 } 0171 return nullptr; 0172 } 0173 0174 void TransferGroup::setUploadLimit(int ulLimit, Transfer::SpeedLimit limit) 0175 { 0176 if (limit == Transfer::VisibleSpeedLimit) { 0177 m_visibleUploadLimit = ulLimit; 0178 if (ulLimit < m_uploadLimit || m_uploadLimit == 0) 0179 m_uploadLimit = ulLimit; 0180 } else { 0181 m_uploadLimit = ulLimit; 0182 } 0183 0184 calculateUploadLimit(); 0185 } 0186 0187 void TransferGroup::setDownloadLimit(int dlLimit, Transfer::SpeedLimit limit) 0188 { 0189 if (limit == Transfer::VisibleSpeedLimit) { 0190 m_visibleDownloadLimit = dlLimit; 0191 if (dlLimit < m_downloadLimit || m_downloadLimit == 0) 0192 m_downloadLimit = dlLimit; 0193 } else { 0194 m_downloadLimit = dlLimit; 0195 } 0196 0197 calculateDownloadLimit(); 0198 } 0199 0200 int TransferGroup::uploadLimit(Transfer::SpeedLimit limit) const 0201 { 0202 if (limit == Transfer::VisibleSpeedLimit) 0203 return m_visibleUploadLimit; 0204 0205 return m_uploadLimit; 0206 } 0207 0208 int TransferGroup::downloadLimit(Transfer::SpeedLimit limit) const 0209 { 0210 if (limit == Transfer::VisibleSpeedLimit) 0211 return m_visibleDownloadLimit; 0212 0213 return m_downloadLimit; 0214 } 0215 0216 void TransferGroup::calculateSpeedLimits() 0217 { 0218 qCDebug(KGET_DEBUG) << "We will calculate the new SpeedLimits now"; 0219 calculateDownloadLimit(); 0220 calculateUploadLimit(); 0221 } 0222 0223 void TransferGroup::calculateDownloadLimit() 0224 { 0225 qCDebug(KGET_DEBUG) << "Calculate new DownloadLimit of " + QString::number(m_downloadLimit); 0226 if (supportsSpeedLimits()) { 0227 const QList<Job *> running = runningJobs(); 0228 int n = running.count(); 0229 int pool = 0; // We create a pool where we have some KiB/s to go to other transfer's... 0230 QList<Transfer *> transfersNeedSpeed; 0231 foreach (Job *job, running) { 0232 auto *transfer = static_cast<Transfer *>(job); 0233 if (transfer) { 0234 if (m_downloadLimit == 0 && transfer->downloadLimit(Transfer::VisibleSpeedLimit) != 0) 0235 continue; 0236 else if (m_downloadLimit == 0 && transfer->downloadLimit(Transfer::VisibleSpeedLimit) == 0) 0237 transfer->setDownloadLimit(0, Transfer::InvisibleSpeedLimit); 0238 else if (transfer->downloadLimit(Transfer::VisibleSpeedLimit) < m_downloadLimit / n 0239 && transfer->downloadLimit(Transfer::VisibleSpeedLimit) != 0) 0240 /*If the transfer's visible download limit is under the new one, 0241 we move the KiB/s which are different to the pool*/ 0242 pool = pool + (m_downloadLimit / n - transfer->downloadLimit(Transfer::VisibleSpeedLimit)); 0243 else if (transfer->downloadSpeed() + 10 < m_downloadLimit / n) { 0244 /*When the downloadSpeed of the transfer is under the new downloadLimit + 10 then we 0245 set the downloadLimit to the downloadSpeed + 10*/ 0246 pool = pool + m_downloadLimit / n - transfer->downloadSpeed() + 10; 0247 transfer->setDownloadLimit(transfer->downloadSpeed() + 10, Transfer::InvisibleSpeedLimit); 0248 } else { 0249 transfer->setDownloadLimit(m_downloadLimit / n, Transfer::InvisibleSpeedLimit); 0250 transfersNeedSpeed.append(transfer); 0251 } 0252 } 0253 } 0254 foreach (Transfer *transfer, transfersNeedSpeed) { 0255 transfer->setDownloadLimit(m_downloadLimit / n + pool / transfersNeedSpeed.count(), Transfer::InvisibleSpeedLimit); 0256 } 0257 } 0258 } 0259 0260 void TransferGroup::calculateUploadLimit() 0261 { 0262 qCDebug(KGET_DEBUG) << "Calculate new Upload Limit of " + QString::number(m_uploadLimit); 0263 if (supportsSpeedLimits()) { 0264 const QList<Job *> running = runningJobs(); 0265 int n = running.count(); 0266 int pool = 0; // We create a pool where we have some KiB/s to go to other transfer's... 0267 QList<Transfer *> transfersNeedSpeed; 0268 foreach (Job *job, running) { 0269 auto *transfer = static_cast<Transfer *>(job); 0270 if (transfer) { 0271 if (m_uploadLimit == 0 && transfer->uploadLimit(Transfer::VisibleSpeedLimit) != 0) 0272 continue; 0273 else if (m_uploadLimit == 0 && transfer->uploadLimit(Transfer::VisibleSpeedLimit) == 0) 0274 transfer->setUploadLimit(0, Transfer::InvisibleSpeedLimit); 0275 else if (transfer->uploadLimit(Transfer::VisibleSpeedLimit) < m_uploadLimit / n && transfer->uploadLimit(Transfer::VisibleSpeedLimit) != 0) 0276 /*If the transfer's visible upload limit is under the new one, 0277 we move the KiB/s which are different to the pool*/ 0278 pool = pool + (m_uploadLimit / n - transfer->uploadLimit(Transfer::VisibleSpeedLimit)); 0279 else if (transfer->uploadSpeed() + 10 < m_uploadLimit / n) { 0280 /*When the uploadSpeed of the transfer is under the new uploadLimit + 10 then we 0281 set the uploadLimit to the uploadSpeed + 10*/ 0282 pool = pool + m_uploadLimit / n - transfer->uploadSpeed() + 10; 0283 transfer->setUploadLimit(transfer->uploadSpeed() + 10, Transfer::InvisibleSpeedLimit); 0284 } else { 0285 transfer->setUploadLimit(m_uploadLimit / n, Transfer::InvisibleSpeedLimit); 0286 transfersNeedSpeed.append(transfer); 0287 } 0288 } 0289 } 0290 foreach (Transfer *transfer, transfersNeedSpeed) { 0291 transfer->setUploadLimit(m_uploadLimit / n + pool / transfersNeedSpeed.count(), Transfer::InvisibleSpeedLimit); 0292 } 0293 } 0294 } 0295 0296 void TransferGroup::save(QDomElement e) // krazy:exclude=passbyvalue 0297 { 0298 // qCDebug(KGET_DEBUG) << " --> " << name(); 0299 0300 e.setAttribute("Name", m_name); 0301 e.setAttribute("DefaultFolder", m_defaultFolder); 0302 e.setAttribute("DownloadLimit", m_visibleDownloadLimit); 0303 e.setAttribute("UploadLimit", m_visibleUploadLimit); 0304 e.setAttribute("Icon", m_iconName); 0305 e.setAttribute("Status", status() == JobQueue::Running ? "Running" : "Stopped"); 0306 e.setAttribute("RegExpPattern", m_regExp.pattern()); 0307 0308 iterator it = begin(); 0309 iterator itEnd = end(); 0310 0311 for (; it != itEnd; ++it) { 0312 auto *transfer = static_cast<Transfer *>(*it); 0313 qCDebug(KGET_DEBUG) << " --> " << name() << " transfer: " << transfer->source(); 0314 QDomElement t = e.ownerDocument().createElement("Transfer"); 0315 e.appendChild(t); 0316 transfer->save(t); 0317 } 0318 } 0319 0320 void TransferGroup::load(const QDomElement &e) 0321 { 0322 qCDebug(KGET_DEBUG) << "TransferGroup::load"; 0323 0324 m_name = e.attribute("Name"); 0325 m_defaultFolder = e.attribute("DefaultFolder"); 0326 m_visibleDownloadLimit = e.attribute("DownloadLimit").toInt(); 0327 m_visibleUploadLimit = e.attribute("UploadLimit").toInt(); 0328 if (!e.attribute("Icon").isEmpty()) 0329 m_iconName = e.attribute("Icon"); 0330 0331 if (e.attribute("Status") == "Running") 0332 setStatus(JobQueue::Running); 0333 else 0334 setStatus(JobQueue::Stopped); 0335 0336 m_regExp.setPattern(e.attribute("RegExpPattern")); 0337 0338 QDomNodeList nodeList = e.elementsByTagName("Transfer"); 0339 int nItems = nodeList.length(); 0340 0341 QList<QDomElement> elements; 0342 for (int i = 0; i < nItems; ++i) { 0343 elements << nodeList.item(i).toElement(); 0344 } 0345 0346 qCDebug(KGET_DEBUG) << "TransferGroup::load ->" 0347 << "add" << nItems << "transfers"; 0348 KGet::addTransfers(elements, name()); 0349 } 0350 0351 #include "moc_transfergroup.cpp"