File indexing completed on 2024-05-05 04:59:19

0001 /*
0002     This file is part of the KDE project
0003     Copyright (C) 2011 Ernesto Rodriguez Ortiz <eortiz@uci.cu>
0004 
0005     This program is free software: you can redistribute it and/or modify
0006     it under the terms of the GNU General Public License as published by
0007     the Free Software Foundation, either version 3 of the License, or
0008     (at your option) any later version.
0009 
0010     This program is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013     GNU General Public License for more details.
0014 
0015     You should have received a copy of the GNU General Public License
0016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 
0018 */
0019 
0020 #include "mmstransfer.h"
0021 
0022 #include "kget_debug.h"
0023 #include <QDebug>
0024 #include <QDir>
0025 #include <QStandardPaths>
0026 
0027 MmsTransfer::MmsTransfer(TransferGroup *parent, TransferFactory *factory, Scheduler *scheduler, const QUrl &source, const QUrl &dest, const QDomElement *e)
0028     : Transfer(parent, factory, scheduler, source, dest, e)
0029     , m_mmsdownload(NULL)
0030     , m_amountThreads(MmsSettings::threads())
0031     , m_retryDownload(false)
0032 {
0033     // make sure that the DataLocation directory exists (earlier this used to be handled by KStandardDirs)
0034     if (!QFileInfo::exists(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))) {
0035         QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
0036     }
0037     m_fileTemp = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + m_dest.fileName();
0038     qCDebug(KGET_DEBUG) << "Mms transfer initialized: " + m_source.toString();
0039 }
0040 
0041 MmsTransfer::~MmsTransfer()
0042 {
0043     /** If m_mmsdownload is not deleted we delete it before end.*/
0044     if (m_mmsdownload) {
0045         m_mmsdownload->quit();
0046         m_mmsdownload->deleteLater();
0047     }
0048 }
0049 
0050 void MmsTransfer::start()
0051 {
0052     /** Starting the download, is created the thread m_mmsdownload and is started the download*/
0053     if (m_mmsdownload || status() == Finished) {
0054         return;
0055     }
0056 
0057     setStatus(Job::Running, i18nc("transfer state: running", "Running...."), "media-playback-start");
0058     m_mmsdownload = new MmsDownload(m_source.toString(), m_dest.toLocalFile(), m_fileTemp, m_amountThreads);
0059     connect(m_mmsdownload, SIGNAL(finished()), this, SLOT(slotResult()));
0060     connect(m_mmsdownload, SIGNAL(signBrokenUrl()), this, SLOT(slotBrokenUrl()));
0061     connect(m_mmsdownload, SIGNAL(signNotAllowMultiDownload()), this, SLOT(slotNotAllowMultiDownload()));
0062     connect(m_mmsdownload, SIGNAL(signTotalSize(qulonglong)), this, SLOT(slotTotalSize(qulonglong)));
0063     connect(m_mmsdownload, SIGNAL(signDownloaded(qulonglong)), this, SLOT(slotProcessedSizeAndPercent(qulonglong)));
0064     connect(m_mmsdownload, SIGNAL(signSpeed(ulong)), this, SLOT(slotSpeed(ulong)));
0065     connect(m_mmsdownload, SIGNAL(signRestartDownload(int)), this, SLOT(slotConnectionsErrors(int)));
0066     m_mmsdownload->start();
0067     setTransferChange(Tc_Status, true);
0068 }
0069 
0070 void MmsTransfer::stop()
0071 {
0072     /** The download is stopped, we call m_mmsdownload->stopTransfer() and when all threads
0073      * are finish m_mmsdownload will be deleted in MmsTransfer::slotResult().
0074      */
0075     if ((status() == Stopped) || (status() == Finished)) {
0076         return;
0077     }
0078 
0079     if (m_mmsdownload) {
0080         if (m_mmsdownload->threadsAlive() > 0) {
0081             m_mmsdownload->stopTransfer();
0082         }
0083     }
0084 
0085     setStatus(Job::Stopped, i18nc("transfer state: stopped", "Stopped"), "process-stop");
0086     m_downloadSpeed = 0;
0087     setTransferChange(Tc_Status | Tc_DownloadSpeed, true);
0088 }
0089 
0090 void MmsTransfer::deinit(Transfer::DeleteOptions options)
0091 {
0092     /** Deleting the temporary file and the unfinish file*/
0093     if (options & Transfer::DeleteFiles) {
0094         KIO::Job *del = KIO::del(QUrl::fromLocalFile(m_fileTemp), KIO::HideProgressInfo);
0095         if (!del->exec()) {
0096             qCDebug(KGET_DEBUG) << "Could not delete " << m_fileTemp;
0097         }
0098         del = KIO::del(m_dest, KIO::HideProgressInfo);
0099         if (!del->exec()) {
0100             qCDebug(KGET_DEBUG) << "Could not delete " << m_dest.path();
0101         }
0102     }
0103 }
0104 
0105 void MmsTransfer::slotResult()
0106 {
0107     /** This slot is connected with the signal finish of m_mmsdownload*/
0108     /** Deleting m_mmsdownload.*/
0109     m_mmsdownload->deleteLater();
0110     m_mmsdownload = NULL;
0111 
0112     /** If the download end without problems is changed the status to Finished and is deleted
0113      * the temporary file where is saved the status of all threads that download the file.
0114      */
0115     if (m_downloadedSize == m_totalSize && m_totalSize != 0) {
0116         setStatus(Job::Finished, i18nc("Transfer State:Finished", "Finished"), "dialog-ok");
0117         m_percent = 100;
0118         m_downloadSpeed = 0;
0119         setTransferChange(Tc_Status | Tc_Percent | Tc_DownloadSpeed, true);
0120         KIO::Job *del = KIO::del(QUrl::fromLocalFile(m_fileTemp), KIO::HideProgressInfo);
0121         if (!del->exec()) {
0122             qCDebug(KGET_DEBUG) << "Could not delete " << m_fileTemp;
0123         }
0124     }
0125 
0126     /** If m_retryDownload == true then some threads has fail to connect, so the download was
0127      * stopped in MmsTransfer::slotConnectionsErrors() and here when all the connected thread
0128      * are finished we delete the temporary file and we start again the download using the amount
0129      * of threads defined in MmsTransfer::slotConnectionsErrors().
0130      */
0131     if (m_retryDownload) {
0132         m_retryDownload = false;
0133         KIO::Job *del = KIO::del(QUrl::fromLocalFile(m_fileTemp), KIO::HideProgressInfo);
0134         if (!del->exec()) {
0135             qCDebug(KGET_DEBUG) << "Could not delete " << m_fileTemp;
0136         }
0137         start();
0138     }
0139 }
0140 
0141 void MmsTransfer::slotTotalSize(qulonglong size)
0142 {
0143     m_totalSize = size;
0144     setTransferChange(Tc_TotalSize, true);
0145 }
0146 
0147 void MmsTransfer::slotSpeed(ulong speed)
0148 {
0149     m_downloadSpeed = (status() == Running) ? speed : 0;
0150     setTransferChange(Tc_DownloadSpeed, true);
0151 }
0152 
0153 void MmsTransfer::slotProcessedSizeAndPercent(qulonglong size)
0154 {
0155     m_downloadedSize = size;
0156     m_percent = (m_downloadedSize * 100) / m_totalSize;
0157     setTransferChange(Tc_DownloadedSize | Tc_Percent, true);
0158 }
0159 
0160 void MmsTransfer::slotBrokenUrl()
0161 {
0162     setError(i18n("Download failed, could not access this URL."), "dialog-cancel", Job::NotSolveable);
0163     setTransferChange(Tc_Status, true);
0164 }
0165 
0166 void MmsTransfer::slotNotAllowMultiDownload()
0167 {
0168     /** Some stream not allow seek in to a position, so we can't use more than one thread to
0169      * download the file, this is notify to the user because the download will take longer.
0170      */
0171     KGet::showNotification(nullptr,
0172                            "notification",
0173                            i18n("This URL does not allow multiple connections,\n"
0174                                 "the download will take longer."));
0175 }
0176 
0177 void MmsTransfer::slotConnectionsErrors(int connections)
0178 {
0179     /** Here is called stop() for stop the download, set a new amount of thread
0180      * and set m_retryDownload = true for restart the download when mmsdownload is finish and
0181      * Q_EMIT a signal connected with MmsTransfer::slotResult(), see in MmsTransfer::slotResult()
0182      * for understand when its started again the download.
0183      */
0184     stop();
0185     m_retryDownload = true;
0186     if (connections) {
0187         m_amountThreads = connections;
0188     } else {
0189         m_amountThreads--;
0190     }
0191 }
0192 
0193 #include "moc_mmstransfer.cpp"