From d76f6bdb544f6ba4fb6b92fbeb36bfe25450eb1f Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Sun, 27 Nov 2011 12:00:28 +0100 Subject: Download Management ++ - let users choose a "default" download dir - Moved download code to download manager - follow dfaure's suggestions about overwrite handling (kdelibs commit 88e3b372fb9c539) - download label notification (for 3 seconds): this can be further improved with an icon... BUG: 271683 BUG: 283177 --- src/downloadmanager.cpp | 144 ++++++++++++++++++++++++++++++++++++++++++ src/downloadmanager.h | 24 +++++-- src/mainwindow.cpp | 4 ++ src/webpage.cpp | 165 ++++-------------------------------------------- 4 files changed, 178 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 490637bf..1f58d99f 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -29,15 +29,32 @@ #include "downloadmanager.h" #include "downloadmanager.moc" +// Auto Includes +#include "rekonq.h" + // KDE Includes #include +#include +#include + +#include + +#include +#include +#include // Qt Includes #include #include #include +#include #include #include +#include + +#include +#include +#include DownloadManager::DownloadManager(QObject *parent) @@ -103,3 +120,130 @@ bool DownloadManager::clearDownloadsHistory() QFile downloadFile(downloadFilePath); return downloadFile.remove(); } + + +void DownloadManager::downloadLinksWithKGet(const QVariant &contentList) +{ + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) + { + KToolInvocation::kdeinitExecWait("kget"); + } + QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); + if (kget.isValid()) + { + kget.call("importLinks", contentList); + } +} + + +// NOTE +// These 2 functions have been copied from the KWebPage class to implement a local version of the downloadResponse method. +// In this way, we can easily provide the extra functionality we need: +// 1. KGet Integration +// 2. Save downloads history +bool DownloadManager::downloadResource(const KUrl &srcUrl, const KIO::MetaData &metaData, QWidget *parent, const QString &suggestedName) +{ + KUrl destUrl; + + int result = KIO::R_OVERWRITE; + const QString fileName((suggestedName.isEmpty() ? srcUrl.fileName() : suggestedName)); + + do + { + if (ReKonfig::askDownloadPath()) + { + // follow bug:184202 fixes + destUrl = KFileDialog::getSaveFileName(KUrl::fromPath(fileName), QString(), parent); + } + else + { + destUrl = KUrl(ReKonfig::downloadPath().path() + QL1C('/') + fileName); + } + + kDebug() << "DEST URL: " << destUrl; + + if (destUrl.isEmpty()) + return false; + + } + while (result == KIO::R_CANCEL && destUrl.isValid()); + + // Save download history + DownloadItem *item = addDownload(srcUrl.pathOrUrl(), destUrl.pathOrUrl()); + emit notifyDownload(fileName); + + if (!KStandardDirs::findExe("kget").isNull() && ReKonfig::kgetDownload()) + { + //KGet integration: + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) + { + KToolInvocation::kdeinitExecWait("kget"); + } + QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); + if (!kget.isValid()) + return false; + + QDBusMessage transfer = kget.call(QL1S("addTransfer"), srcUrl.prettyUrl(), destUrl.prettyUrl(), true); + if (transfer.arguments().isEmpty()) + return true; + + const QString transferPath = transfer.arguments().first().toString(); + item->setKGetTransferDbusPath(transferPath); + return true; + } + + KIO::Job *job = KIO::copy(srcUrl, destUrl, KIO::Overwrite); + if (item) + { + QObject::connect(job, SIGNAL(percent(KJob *, unsigned long)), item, SLOT(updateProgress(KJob *, unsigned long))); + QObject::connect(job, SIGNAL(finished(KJob *)), item, SLOT(onFinished(KJob*))); + } + + if (!metaData.isEmpty()) + job->setMetaData(metaData); + + job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache. + job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available. + job->uiDelegate()->setAutoErrorHandlingEnabled(true); + return true; +} + + +// ------------------------------------------------------------------------------------------------------------------- + + +// STATIC +void DownloadManager::extractSuggestedFileName(const QNetworkReply* reply, QString& fileName) +{ + fileName.clear(); + const KIO::MetaData& metaData = reply->attribute(static_cast(KIO::AccessManager::MetaData)).toMap(); + if (metaData.value(QL1S("content-disposition-type")).compare(QL1S("attachment"), Qt::CaseInsensitive) == 0) + fileName = metaData.value(QL1S("content-disposition-filename")); + + if (!fileName.isEmpty()) + return; + + if (!reply->hasRawHeader("Content-Disposition")) + return; + + const QString value(QL1S(reply->rawHeader("Content-Disposition").simplified().constData())); + if (value.startsWith(QL1S("attachment"), Qt::CaseInsensitive) || value.startsWith(QL1S("inline"), Qt::CaseInsensitive)) + { + const int length = value.size(); + int pos = value.indexOf(QL1S("filename"), 0, Qt::CaseInsensitive); + if (pos > -1) + { + pos += 9; + while (pos < length && (value.at(pos) == QL1C(' ') || value.at(pos) == QL1C('=') || value.at(pos) == QL1C('"'))) + pos++; + + int endPos = pos; + while (endPos < length && value.at(endPos) != QL1C('"') && value.at(endPos) != QL1C(';')) + endPos++; + + if (endPos > pos) + fileName = value.mid(pos, (endPos - pos)).trimmed(); + } + } +} + diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 2955904c..e450d261 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -34,12 +34,16 @@ // Local Includes #include "downloaditem.h" +// KDE Includes +#include + // Qt Includes #include +#include - - -// --------------------------------------------------------------------------------- +// Forward Includes +class KUrl; +class QNetworkReply; class REKONQ_TESTS_EXPORT DownloadManager : public QObject @@ -53,16 +57,24 @@ public: { return m_downloadList; } - DownloadItem* addDownload(const QString &srcUrl, const QString &destUrl); bool clearDownloadsHistory(); + bool downloadResource(const KUrl &url, const KIO::MetaData &metaData = KIO::MetaData(), + QWidget *parent = 0, const QString &suggestedName = QString()); + + void downloadLinksWithKGet(const QVariant &contentList); + + static void extractSuggestedFileName(const QNetworkReply* reply, QString& fileName); + Q_SIGNALS: void newDownloadAdded(QObject *item); + void notifyDownload(const QString&, Rekonq::Notify = Rekonq::Download); private: - DownloadList m_downloadList; - void init(); + DownloadItem* addDownload(const QString &srcUrl, const QString &destUrl); + + DownloadList m_downloadList; }; #endif // DOWNLOADMANAGER_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d7b45a32..ec3098c3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -179,6 +179,8 @@ MainWindow::MainWindow() // notification system connect(m_view, SIGNAL(showStatusBarMessage(const QString&, Rekonq::Notify)), this, SLOT(notifyMessage(const QString&, Rekonq::Notify))); connect(m_view, SIGNAL(linkHovered(const QString&)), this, SLOT(notifyMessage(const QString&))); + connect(rApp->downloadManager(), SIGNAL(notifyDownload(const QString&, Rekonq::Notify)), + this, SLOT(notifyMessage(const QString&, Rekonq::Notify))); // connect signals and slots connect(m_view, SIGNAL(currentTitle(const QString &)), this, SLOT(updateWindowTitle(const QString &))); @@ -1193,6 +1195,8 @@ void MainWindow::notifyMessage(const QString &msg, Rekonq::Notify status) case Rekonq::Success: case Rekonq::Error: case Rekonq::Download: + m_hidePopupTimer->start(3000); + break; default: break; } diff --git a/src/webpage.cpp b/src/webpage.cpp index a9ac1a84..647b1ccb 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -54,36 +54,24 @@ #include "sslinfodialog.h" // KDE Includes -#include -#include -#include - #include #include -#include #include #include #include #include #include -#include #include #include #include -#include +#include -#include +#include // Qt Includes -#include - #include -#include -#include -#include - // Returns true if the scheme and domain of the two urls match... static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) @@ -107,46 +95,6 @@ static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) } -// NOTE -// These 2 functions have been copied from the KWebPage class to implement a local version of the downloadResponse method. -// In this way, we can easily provide the extra functionality we need: -// 1. KGet Integration -// 2. Save downloads history -static void extractSuggestedFileName(const QNetworkReply* reply, QString& fileName) -{ - fileName.clear(); - const KIO::MetaData& metaData = reply->attribute(static_cast(KIO::AccessManager::MetaData)).toMap(); - if (metaData.value(QL1S("content-disposition-type")).compare(QL1S("attachment"), Qt::CaseInsensitive) == 0) - fileName = metaData.value(QL1S("content-disposition-filename")); - - if (!fileName.isEmpty()) - return; - - if (!reply->hasRawHeader("Content-Disposition")) - return; - - const QString value(QL1S(reply->rawHeader("Content-Disposition").simplified().constData())); - if (value.startsWith(QL1S("attachment"), Qt::CaseInsensitive) || value.startsWith(QL1S("inline"), Qt::CaseInsensitive)) - { - const int length = value.size(); - int pos = value.indexOf(QL1S("filename"), 0, Qt::CaseInsensitive); - if (pos > -1) - { - pos += 9; - while (pos < length && (value.at(pos) == QL1C(' ') || value.at(pos) == QL1C('=') || value.at(pos) == QL1C('"'))) - pos++; - - int endPos = pos; - while (endPos < length && value.at(endPos) != QL1C('"') && value.at(endPos) != QL1C(';')) - endPos++; - - if (endPos > pos) - fileName = value.mid(pos, (endPos - pos)).trimmed(); - } - } -} - - static void extractMimeType(const QNetworkReply* reply, QString& mimeType) { mimeType.clear(); @@ -169,87 +117,6 @@ static void extractMimeType(const QNetworkReply* reply, QString& mimeType) } -static bool downloadResource(const KUrl& srcUrl, const KIO::MetaData& metaData = KIO::MetaData(), - QWidget * parent = 0, const QString & suggestedName = QString()) -{ - KUrl destUrl; - - int result = KIO::R_OVERWRITE; - const QString fileName((suggestedName.isEmpty() ? srcUrl.fileName() : suggestedName)); - - do - { - // follow bug:184202 fixes - destUrl = KFileDialog::getSaveFileName(KUrl::fromPath(fileName), QString(), parent); - - if (destUrl.isEmpty()) - return false; - - if (destUrl.isLocalFile()) - { - QFileInfo finfo(destUrl.toLocalFile()); - if (finfo.exists()) - { - QDateTime now = QDateTime::currentDateTime(); - QPointer dlg = new KIO::RenameDialog(parent, - i18n("Overwrite File?"), - srcUrl, - destUrl, - KIO::RenameDialog_Mode(KIO::M_OVERWRITE | KIO::M_SKIP), - -1, - finfo.size(), - now.toTime_t(), - finfo.created().toTime_t(), - now.toTime_t(), - finfo.lastModified().toTime_t() - ); - result = dlg->exec(); - delete dlg; - } - } - } - while (result == KIO::R_CANCEL && destUrl.isValid()); - - // Save download history - DownloadItem *item = rApp->downloadManager()->addDownload(srcUrl.pathOrUrl(), destUrl.pathOrUrl()); - - if (!KStandardDirs::findExe("kget").isNull() && ReKonfig::kgetDownload()) - { - //KGet integration: - if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) - { - KToolInvocation::kdeinitExecWait("kget"); - } - QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); - if (!kget.isValid()) - return false; - - QDBusMessage transfer = kget.call(QL1S("addTransfer"), srcUrl.prettyUrl(), destUrl.prettyUrl(), true); - if (transfer.arguments().isEmpty()) - return true; - - const QString transferPath = transfer.arguments().first().toString(); - item->setKGetTransferDbusPath(transferPath); - return true; - } - - KIO::Job *job = KIO::file_copy(srcUrl, destUrl, -1, KIO::Overwrite); - if (item) - { - QObject::connect(job, SIGNAL(percent(KJob *, unsigned long)), item, SLOT(updateProgress(KJob *, unsigned long))); - QObject::connect(job, SIGNAL(finished(KJob *)), item, SLOT(onFinished(KJob*))); - } - - if (!metaData.isEmpty()) - job->setMetaData(metaData); - - job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache. - job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available. - job->uiDelegate()->setAutoErrorHandlingEnabled(true); - return true; -} - - // --------------------------------------------------------------------------------- @@ -410,9 +277,6 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) KIO::Integration::AccessManager::putReplyOnHold(reply); - // Get suggested file name... - extractSuggestedFileName(reply, _suggestedFileName); - // Get mimeType... extractMimeType(reply, _mimeType); @@ -441,6 +305,9 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) if (!isLocal) { KParts::BrowserOpenOrSaveQuestion dlg(rApp->mainWindow(), replyUrl, _mimeType); + + // Get suggested file name... + DownloadManager::extractSuggestedFileName(reply, _suggestedFileName); if (!_suggestedFileName.isEmpty()) dlg.setSuggestedFileName(_suggestedFileName); @@ -543,7 +410,7 @@ void WebPage::manageNetworkErrors(QNetworkReply *reply) // check suggested file name if (_suggestedFileName.isEmpty()) - extractSuggestedFileName(reply, _suggestedFileName); + DownloadManager::extractSuggestedFileName(reply, _suggestedFileName); QWebFrame* frame = qobject_cast(reply->request().originatingObject()); const bool isMainFrameRequest = (frame == mainFrame()); @@ -678,21 +545,21 @@ QString WebPage::errorPage(QNetworkReply *reply) void WebPage::downloadReply(const QNetworkReply *reply, const QString &suggestedFileName) { - downloadResource(reply->url(), KIO::MetaData(), view(), suggestedFileName); + rApp->downloadManager()->downloadResource(reply->url(), KIO::MetaData(), view(), suggestedFileName); } void WebPage::downloadRequest(const QNetworkRequest &request) { - downloadResource(request.url(), - request.attribute(static_cast(KIO::AccessManager::MetaData)).toMap(), - view()); + rApp->downloadManager()->downloadResource(request.url(), + request.attribute(static_cast(KIO::AccessManager::MetaData)).toMap(), + view()); } void WebPage::downloadUrl(const KUrl &url) { - downloadResource(url, KIO::MetaData(), view()); + rApp->downloadManager()->downloadResource(url, KIO::MetaData(), view()); } @@ -716,15 +583,7 @@ void WebPage::downloadAllContentsWithKGet() contents << baseUrl.resolved(relativeUrl).toString(); } - if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kget")) - { - KToolInvocation::kdeinitExecWait("kget"); - } - QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); - if (kget.isValid()) - { - kget.call("importLinks", QVariant(contents.toList())); - } + rApp->downloadManager()->downloadLinksWithKGet(QVariant(contents.toList())); } -- cgit v1.2.1