From 47bd57b5027f0fe34a6619d3d1902a9e67a16673 Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Thu, 26 May 2011 00:12:01 +0200 Subject: Adding DownloadManager class, following Pierre and Benjamin code changes. First step in the introduction of the new rekonq pages --- src/CMakeLists.txt | 2 + src/application.cpp | 67 ++++--------------- src/application.h | 39 +++-------- src/downloaditem.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ src/downloaditem.h | 103 +++++++++++++++++++++++++++++ src/downloadmanager.cpp | 105 ++++++++++++++++++++++++++++++ src/downloadmanager.h | 65 +++++++++++++++++++ src/mainwindow.cpp | 3 +- src/newtabpage.cpp | 11 ++-- src/webpage.cpp | 25 ++++--- 10 files changed, 489 insertions(+), 99 deletions(-) create mode 100644 src/downloaditem.cpp create mode 100644 src/downloaditem.h create mode 100644 src/downloadmanager.cpp create mode 100644 src/downloadmanager.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e197f59..db9506aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,8 @@ ADD_SUBDIRECTORY( tests ) SET( rekonq_KDEINIT_SRCS application.cpp clicktoflash.cpp + downloaditem.cpp + downloadmanager.cpp filterurljob.cpp findbar.cpp iconmanager.cpp diff --git a/src/application.cpp b/src/application.cpp index 830442f0..311c90a2 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -36,6 +36,7 @@ // Local Includes #include "adblockmanager.h" #include "bookmarkprovider.h" +#include "downloadmanager.h" #include "filterurljob.h" #include "historymanager.h" #include "iconmanager.h" @@ -355,6 +356,16 @@ IconManager *Application::iconManager() } +DownloadManager *Application::downloadManager() +{ + if (m_downloadManager.isNull()) + { + m_downloadManager = new DownloadManager(instance()); + } + return m_downloadManager.data(); +} + + void Application::loadUrl(const KUrl& url, const Rekonq::OpenType& type) { if (url.isEmpty()) @@ -622,62 +633,6 @@ void Application::updateConfiguration() } -void Application::addDownload(const QString &srcUrl, const QString &destUrl) -{ - QWebSettings *globalSettings = QWebSettings::globalSettings(); - if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled)) - return; - QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); - QFile downloadFile(downloadFilePath); - if (!downloadFile.open(QFile::WriteOnly | QFile::Append)) - { - kDebug() << "Unable to open download file (WRITE mode).."; - return; - } - QDataStream out(&downloadFile); - out << srcUrl; - out << destUrl; - out << QDateTime::currentDateTime(); - downloadFile.close(); -} - - -DownloadList Application::downloads() -{ - DownloadList list; - - QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); - QFile downloadFile(downloadFilePath); - if (!downloadFile.open(QFile::ReadOnly)) - { - kDebug() << "Unable to open download file (READ mode).."; - return list; - } - - QDataStream in(&downloadFile); - while (!in.atEnd()) - { - QString srcUrl; - in >> srcUrl; - QString destUrl; - in >> destUrl; - QDateTime dt; - in >> dt; - DownloadItem item(srcUrl, destUrl, dt); - list << item; - } - return list; -} - - -bool Application::clearDownloadsHistory() -{ - QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); - QFile downloadFile(downloadFilePath); - return downloadFile.remove(); -} - - void Application::setPrivateBrowsingMode(bool b) { // NOTE diff --git a/src/application.h b/src/application.h index d3757645..f56c36ac 100644 --- a/src/application.h +++ b/src/application.h @@ -33,6 +33,9 @@ // Rekonq Includes #include "rekonq_defines.h" +// Local Includes +#include "downloaditem.h" + // KDE Includes #include @@ -43,7 +46,7 @@ // Forward Declarations class AdBlockManager; class BookmarkProvider; -class DownloadItem; +class DownloadManager; class HistoryManager; class IconManager; class MainWindow; @@ -54,39 +57,20 @@ class KAction; namespace ThreadWeaver { -class Job; + class Job; } typedef QList< QWeakPointer > MainWindowList; -typedef QList DownloadList; - - -class DownloadItem -{ -public: - DownloadItem() {} - explicit DownloadItem(const QString &srcUrl, - const QString &destUrl, - const QDateTime &d - ) - : srcUrlString(srcUrl) - , destUrlString(destUrl) - , dateTime(d) - {} - - QString srcUrlString; - QString destUrlString; - QDateTime dateTime; -}; // --------------------------------------------------------------------------------------------------------------- + #define rApp Application::instance() /** - * + * Rekonq Application class */ class REKONQ_TESTS_EXPORT Application : public KUniqueApplication { @@ -108,12 +92,8 @@ public: AdBlockManager *adblockManager(); OpenSearchManager *opensearchManager(); IconManager *iconManager(); - - // DOWNLOADS MANAGEMENT METHODS - void addDownload(const QString &srcUrl, const QString &destUrl); - DownloadList downloads(); - bool clearDownloadsHistory(); - + DownloadManager *downloadManager(); + KAction *privateBrowsingAction() { return _privateBrowsingAction; @@ -158,6 +138,7 @@ private: QWeakPointer m_adblockManager; QWeakPointer m_opensearchManager; QWeakPointer m_iconManager; + QWeakPointer m_downloadManager; MainWindowList m_mainWindows; diff --git a/src/downloaditem.cpp b/src/downloaditem.cpp new file mode 100644 index 00000000..d1f8ec9e --- /dev/null +++ b/src/downloaditem.cpp @@ -0,0 +1,168 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2011 by Pierre Rossi +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* ============================================================ */ + + +// Self includes +#include "downloaditem.h" +#include "downloaditem.moc" + +// Qt Includes +#include +#include + +// KDE Includes +#include +#include +#include +#include + + +DownloadItem::DownloadItem(const QString &srcUrl, const QString &destUrl, const QDateTime &d, QObject *parent) + : QObject(parent) + , m_srcUrlString(srcUrl) + , m_destUrl(KUrl(destUrl)) + , m_dateTime(d) + , m_shouldAbort(false) +{ +} + + +QString DownloadItem::fileDirectory() const +{ + return (QL1S("file://") + m_destUrl.directory()); +} + + +QString DownloadItem::fileName() const +{ + return m_destUrl.fileName(); +} + + +QString DownloadItem::destinationUrl() const +{ + return m_destUrl.url(KUrl::RemoveTrailingSlash); +} + + +QString DownloadItem::icon() const +{ + KIconLoader *loader = KIconLoader::global(); + QString iconForMimeType = KMimeType::iconNameForUrl(m_destUrl); + return (QL1S("file://") + loader->iconPath(iconForMimeType, KIconLoader::Desktop)); +} + + +// update progress for the plain KIO::Job backend +void DownloadItem::updateProgress(KJob *job, unsigned long value) +{ + if (m_shouldAbort) + job->kill(KJob::EmitResult); + emit downloadProgress(value); +} + + +// emit downloadFinished signal in KJob case +void DownloadItem::onFinished(KJob *job) +{ + if (!job->error()) + emit downloadProgress(100); + emit downloadFinished(!job->error()); +} + + +// sets up progress handling for the KGet backend +void DownloadItem::setKGetTransferDbusPath(const QString &path) +{ + m_kGetPath = path; + QTimer *updateTimer = new QTimer(this); + updateTimer->setInterval(300); + updateTimer->setSingleShot(false); + connect(updateTimer, SIGNAL(timeout()), SLOT(updateProgress())); + updateTimer->start(); +} + + +/* +* update progress (polling in KGet case) +* +* Notes for KGet dbus interface: +* status values: +* - 0 running +* - 2 stopped +* - 4 finished +*/ +void DownloadItem::updateProgress() +{ + if (m_kGetPath.isEmpty()) + return; + QDBusInterface kgetTransfer(QL1S("org.kde.kget"), m_kGetPath, QL1S("org.kde.kget.transfer")); + if (!kgetTransfer.isValid()) + return; + // Fetch percent from DBus + QDBusMessage percentRes = kgetTransfer.call(QL1S("percent")); + if (percentRes.arguments().isEmpty()) + return; + bool ok = false; + const int percent = percentRes.arguments().first().toInt(&ok); + if (!ok) + return; + // Fetch status from DBus + QDBusMessage statusRes = kgetTransfer.call(QL1S("status")); + if (statusRes.arguments().isEmpty()) + return; + ok = false; + const int status = statusRes.arguments().first().toInt(&ok); + if (!ok) + return; + emit downloadProgress(percent); + // TODO: expose resume if stopped + // special case for status 2 will come later when we have a way to support resume. + if (percent == 100 || status == 4 || status == 2) { + emit downloadFinished(true); + QTimer *timer = qobject_cast(sender()); + if (timer) + timer->stop(); + } +} + + +void DownloadItem::abort() const +{ + if (!m_kGetPath.isEmpty()) + { + QDBusInterface kgetTransfer(QL1S("org.kde.kget"), m_kGetPath, QL1S("org.kde.kget.transfer")); + if (kgetTransfer.isValid()) + kgetTransfer.call(QL1S("stop")); + } + else + { + // using KIO::JOB, kill at the next update :) + m_shouldAbort = true; + } +} + +// TODO: ability to remove single items from the page... diff --git a/src/downloaditem.h b/src/downloaditem.h new file mode 100644 index 00000000..80f905bb --- /dev/null +++ b/src/downloaditem.h @@ -0,0 +1,103 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2011 by Pierre Rossi +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* ============================================================ */ + + +#ifndef DOWNLOADITEM_H +#define DOWNLOADITEM_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Qt Includes +#include +#include +#include + +// KDE Includes +#include +#include + +// Forward Declarations +class KJob; + + +class DownloadItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString destinationUrl READ destinationUrl) + Q_PROPERTY(QString originUrl READ originUrl) + Q_PROPERTY(QString fileName READ fileName) + Q_PROPERTY(QString fileDirectory READ fileDirectory) + Q_PROPERTY(QDateTime date READ dateTime()) + Q_PROPERTY(QString iconFile READ icon) + +public: + explicit DownloadItem(const QString &srcUrl, const QString &destUrl, const QDateTime &d, QObject *parent = 0); + + inline QDateTime dateTime() const { return m_dateTime; } + inline QString originUrl() const { return m_srcUrlString; } + QString destinationUrl() const; + QString fileName() const; + QString fileDirectory() const; + QString icon() const; + + // Necessary to provide i18nized strings to javascript. + Q_INVOKABLE QString i18nOpenDir() const { return i18n("Open directory"); } + Q_INVOKABLE QString i18nOpenFile() const { return i18n("Open file"); } + + // For transfer control and notification + void setKGetTransferDbusPath(const QString &path); + Q_INVOKABLE void abort() const; + +Q_SIGNALS: + void downloadProgress(int percent); + void downloadFinished(bool success); + +public Q_SLOTS: + void updateProgress(KJob *job, unsigned long value); + void onFinished(KJob *job); + +private Q_SLOTS: + void updateProgress(); + +private: + QString m_srcUrlString; + KUrl m_destUrl; + QDateTime m_dateTime; + QString m_kGetPath; + mutable bool m_shouldAbort; + KJob *m_job; +}; + + +Q_DECLARE_METATYPE(DownloadItem*); + + +typedef QList DownloadList; + + +#endif //DOWNLAODITEM_H diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp new file mode 100644 index 00000000..490637bf --- /dev/null +++ b/src/downloadmanager.cpp @@ -0,0 +1,105 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2008-2010 by Andrea Diamantini +* Copyright (C) 2011 by Pierre Rossi +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* ============================================================ */ + + +// Self Includes +#include "downloadmanager.h" +#include "downloadmanager.moc" + +// KDE Includes +#include + +// Qt Includes +#include +#include +#include +#include +#include + + +DownloadManager::DownloadManager(QObject *parent) + : QObject(parent) +{ + init(); +} + + +void DownloadManager::init() +{ + QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); + QFile downloadFile(downloadFilePath); + if (!downloadFile.open(QFile::ReadOnly)) + { + kDebug() << "Unable to open download file (READ mode).."; + return; + } + + QDataStream in(&downloadFile); + while (!in.atEnd()) + { + QString srcUrl; + in >> srcUrl; + QString destUrl; + in >> destUrl; + QDateTime dt; + in >> dt; + DownloadItem *item = new DownloadItem(srcUrl, destUrl, dt, this); + m_downloadList.append(item); + } +} + + +DownloadItem* DownloadManager::addDownload(const QString &srcUrl, const QString &destUrl) +{ + QWebSettings *globalSettings = QWebSettings::globalSettings(); + if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled)) + return 0; + QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); + QFile downloadFile(downloadFilePath); + if (!downloadFile.open(QFile::WriteOnly | QFile::Append)) + { + kDebug() << "Unable to open download file (WRITE mode).."; + return 0; + } + QDataStream out(&downloadFile); + out << srcUrl; + out << destUrl; + out << QDateTime::currentDateTime(); + downloadFile.close(); + DownloadItem *item = new DownloadItem(srcUrl, destUrl, QDateTime::currentDateTime(), this); + m_downloadList.append(item); + emit newDownloadAdded(item); + return item; +} + + +bool DownloadManager::clearDownloadsHistory() +{ + m_downloadList.clear(); + QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); + QFile downloadFile(downloadFilePath); + return downloadFile.remove(); +} diff --git a/src/downloadmanager.h b/src/downloadmanager.h new file mode 100644 index 00000000..d96c46de --- /dev/null +++ b/src/downloadmanager.h @@ -0,0 +1,65 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2011 by Pierre Rossi +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* ============================================================ */ + + +#ifndef DOWNLOADMANAGER_H +#define DOWNLOADMANAGER_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Local Includes +#include "downloaditem.h" + +// Qt Includes +#include + + + +// --------------------------------------------------------------------------------- + + +class REKONQ_TESTS_EXPORT DownloadManager : public QObject +{ + Q_OBJECT + +public: + DownloadManager(QObject *parent = 0); + + DownloadList downloads() const { return m_downloadList; } + DownloadItem* addDownload(const QString &srcUrl, const QString &destUrl); + bool clearDownloadsHistory(); + +Q_SIGNALS: + void newDownloadAdded(QObject *item); + +private: + DownloadList m_downloadList; + + void init(); +}; + +#endif // DOWNLOADMANAGER_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e5818677..e401a93e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -40,6 +40,7 @@ #include "bookmarkprovider.h" #include "bookmarkspanel.h" #include "bookmarkstoolbar.h" +#include "downloadmanager.h" #include "findbar.h" #include "historypanel.h" #include "iconmanager.h" @@ -1289,7 +1290,7 @@ void MainWindow::clearPrivateData() if (clearWidget.clearDownloads->isChecked()) { - rApp->clearDownloadsHistory(); + rApp->downloadManager()->clearDownloadsHistory(); } if (clearWidget.clearCookies->isChecked()) diff --git a/src/newtabpage.cpp b/src/newtabpage.cpp index 1dd8b462..940e2c4f 100644 --- a/src/newtabpage.cpp +++ b/src/newtabpage.cpp @@ -35,6 +35,7 @@ // Local Includes #include "application.h" #include "bookmarkprovider.h" +#include "downloadmanager.h" #include "historymodels.h" #include "mainview.h" #include "mainwindow.h" @@ -560,7 +561,7 @@ void NewTabPage::downloadsPage() KIconLoader::Toolbar); m_root.document().findFirst(QL1S("#actions")).appendInside(clearData); - DownloadList list = rApp->downloads(); + DownloadList list = rApp->downloadManager()->downloads(); if (list.isEmpty()) { @@ -569,14 +570,14 @@ void NewTabPage::downloadsPage() return; } - foreach(const DownloadItem &item, list) + foreach(DownloadItem *item, list) { m_root.prependInside(markup(QL1S("div"))); QWebElement div = m_root.firstChild(); div.addClass(QL1S("download")); - KUrl u = KUrl(item.destUrlString); + KUrl u = KUrl(item->destinationUrl()); QString fName = u.fileName(); QString dir = QL1S("file://") + u.directory(); QString file = dir + QL1C('/') + fName; @@ -589,11 +590,11 @@ void NewTabPage::downloadsPage() div.appendInside(QL1S("") + fName + QL1S("")); div.appendInside(QL1S(" - ")); - QString date = KGlobal::locale()->formatDateTime(item.dateTime, KLocale::FancyLongDate); + QString date = KGlobal::locale()->formatDateTime(item->dateTime(), KLocale::FancyLongDate); div.appendInside(QL1S("") + date + QL1S("")); div.appendInside(QL1S("
")); - div.appendInside(QL1S("")); + div.appendInside(QL1S("")); div.appendInside(QL1S("
")); div.appendInside(markup(QL1S("a"))); diff --git a/src/webpage.cpp b/src/webpage.cpp index 3e2798d3..29ee4a40 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -40,6 +40,7 @@ // Local Includes #include "adblockmanager.h" #include "application.h" +#include "downloadmanager.h" #include "iconmanager.h" #include "mainview.h" #include "mainwindow.h" @@ -209,7 +210,7 @@ static bool downloadResource(const KUrl& srcUrl, const KIO::MetaData& metaData = while (result == KIO::R_CANCEL && destUrl.isValid()); // Save download history - rApp->addDownload(srcUrl.pathOrUrl() , destUrl.pathOrUrl()); + DownloadItem *item = rApp->downloadManager()->addDownload(srcUrl.pathOrUrl(), destUrl.pathOrUrl()); if (!KStandardDirs::findExe("kget").isNull() && ReKonfig::kgetDownload()) { @@ -219,16 +220,25 @@ static bool downloadResource(const KUrl& srcUrl, const KIO::MetaData& metaData = KToolInvocation::kdeinitExecWait("kget"); } QDBusInterface kget("org.kde.kget", "/KGet", "org.kde.kget.main"); - if (kget.isValid()) - { - kget.call("addTransfer", srcUrl.prettyUrl(), destUrl.prettyUrl(), true); + if (!kget.isValid()) + return false; + + QDBusMessage transfer = kget.call(QL1S("addTransfer"), srcUrl.prettyUrl(), destUrl.prettyUrl(), true); + if (transfer.arguments().isEmpty()) return true; - } - return false; + + 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); @@ -236,7 +246,6 @@ static bool downloadResource(const KUrl& srcUrl, const KIO::MetaData& metaData = job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available. job->uiDelegate()->setAutoErrorHandlingEnabled(true); return true; - } -- cgit v1.2.1 From 146575c0b2099142653a261ea508a7637c6dadfd Mon Sep 17 00:00:00 2001 From: Andrea Diamantini Date: Thu, 26 May 2011 00:16:10 +0200 Subject: Last --- src/application.cpp | 8 ++++++++ src/application.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/application.cpp b/src/application.cpp index 311c90a2..c00f3f96 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -126,6 +126,14 @@ Application::~Application() m_adblockManager.clear(); } + // TODO: + // add a check to NOT close rekonq + // until last download is finished + + if (!m_downloadManager.isNull()) { + delete m_adblockManager.data(); + m_adblockManager.clear(); + } } diff --git a/src/application.h b/src/application.h index f56c36ac..ec377a71 100644 --- a/src/application.h +++ b/src/application.h @@ -79,6 +79,7 @@ class REKONQ_TESTS_EXPORT Application : public KUniqueApplication public: Application(); ~Application(); + int newInstance(); static Application *instance(); -- cgit v1.2.1