diff options
-rw-r--r-- | src/application.cpp | 19 | ||||
-rw-r--r-- | src/application.h | 22 | ||||
-rw-r--r-- | src/download.cpp | 184 | ||||
-rw-r--r-- | src/download.h | 76 | ||||
-rw-r--r-- | src/mainwindow.cpp | 10 | ||||
-rw-r--r-- | src/rekonq.kcfg | 3 | ||||
-rw-r--r-- | src/settings_general.ui | 7 | ||||
-rw-r--r-- | src/webview.cpp | 4 |
8 files changed, 265 insertions, 60 deletions
diff --git a/src/application.cpp b/src/application.cpp index 65f6e8a8..3399dde4 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -50,7 +50,7 @@ HistoryManager *Application::s_historyManager = 0; NetworkAccessManager *Application::s_networkAccessManager = 0; - +DownloadManager *Application::s_downloadManager = 0; Application::Application() : KUniqueApplication() @@ -67,6 +67,7 @@ Application::Application() Application::~Application() { + delete s_downloadManager; delete s_networkAccessManager; delete s_historyManager; } @@ -117,12 +118,6 @@ void Application::postLaunch() } -void Application::downloadUrl(const KUrl &srcUrl, const KUrl &destUrl) -{ - new Download(srcUrl, destUrl); -} - - void Application::openUrl(const KUrl &url) { mainWindow()->loadUrl(url); @@ -169,6 +164,16 @@ HistoryManager *Application::historyManager() } +DownloadManager *Application::downloadManager() +{ + if (!s_downloadManager) + { + s_downloadManager = new DownloadManager(); + } + return s_downloadManager; +} + + KIcon Application::icon(const KUrl &url) const { KIcon icon = KIcon(QWebSettings::iconForUrl(url)); diff --git a/src/application.h b/src/application.h index 654d554f..8393e184 100644 --- a/src/application.h +++ b/src/application.h @@ -19,8 +19,12 @@ -#ifndef REKONQ_APPLICATION_H -#define REKONQ_APPLICATION_H +#ifndef APPLICATION_H +#define APPLICATION_H + + +// Local Includes +#include "download.h" // KDE Includes #include <KUniqueApplication> @@ -31,12 +35,14 @@ #include <kio/job.h> #include <kio/jobclasses.h> + // Forward Declarations class MainWindow; class WebView; -class CookieJar; class HistoryManager; +class CookieJar; class NetworkAccessManager; +class DownloadManager; /** * @@ -56,15 +62,10 @@ public: KIcon icon(const KUrl &url) const; - /** - * This method lets you to download a file from a source remote url - * to a local destination url. - */ - void downloadUrl(const KUrl &srcUrl, const KUrl &destUrl); - static HistoryManager *historyManager(); static CookieJar *cookieJar(); static NetworkAccessManager *networkAccessManager(); + static DownloadManager *downloadManager(); private slots: @@ -77,9 +78,10 @@ private slots: private: static HistoryManager *s_historyManager; static NetworkAccessManager *s_networkAccessManager; + static DownloadManager *s_downloadManager; MainWindow* m_mainWindow; }; -#endif // REKONQ_APPLICATION_H +#endif // APPLICATION_H diff --git a/src/download.cpp b/src/download.cpp index 9de8dd36..dba7f98f 100644 --- a/src/download.cpp +++ b/src/download.cpp @@ -18,26 +18,165 @@ * * ============================================================ */ + // local Includes #include "download.h" #include "download.moc" // KDE Includes #include <KDebug> +#include <KFileDialog> +#include <KGlobalSettings> +#include <KMessageBox> +#include <KMimeType> +#include <KStandardDirs> // Qt Includes #include <QFile> #include <QFileInfo> +// Local Includes +#include "application.h" +#include "mainwindow.h" + + +DownloadManager::DownloadManager() + : QObject() +{ +} + + +DownloadManager::~DownloadManager() +{ + foreach(Download *download, m_downloads) + { + // cancel all unfinished downloads + download->cancel(); + delete download; + } +} + + +void DownloadManager::newDownload(const KUrl &srcUrl, const KUrl &destUrl) +{ + KUrl destination = destUrl; + Download::DownloadType type; + + KSharedPtr<KMimeType> mimeType = KMimeType::findByPath(srcUrl.prettyUrl()); + + QString typeText = KMimeType::extractKnownExtension(srcUrl.fileName()); + typeText += " (" + mimeType->name() + ")"; + + int answer = KMessageBox::questionYesNoCancel( NULL, + i18n("Download '%1'?\n""Type: %2", srcUrl.prettyUrl(), typeText ), + i18n("Download '%1'...", srcUrl.fileName() ), + KStandardGuiItem::save(), + KStandardGuiItem::open(), + KStandardGuiItem::cancel(), + "showOpenSaveDownloadDialog" + ); + + switch(answer) + { + case KMessageBox::Cancel: + return; + break; + + case KMessageBox::Yes: // ----- SAVE + // if destination is empty than ask for download path (if showOpenSaveDownloadDialog setting enabled) + if (destination.isEmpty()) + { + destination = downloadDestination(srcUrl.fileName()); + } + type = Download::Save; + break; + + case KMessageBox::No: // ----- OPEN + // Download file to tmp dir + destination.setDirectory(KStandardDirs::locateLocal("tmp", "", true)); + destination.addPath(srcUrl.fileName()); + type = Download::Open; + break; + + default: + // impossible + break; + }; + + // if user canceled download than abort + if (destination.isEmpty()) + return; + + Download *download = new Download(srcUrl, destination, type); + connect(download, SIGNAL(downloadFinished(int)), this, SLOT(slotDownloadFinished(int))); + m_downloads.append(download); +} + -Download::Download(const KUrl &srcUrl, const KUrl &destUrl) +const QList<Download *> &DownloadManager::downloads() const +{ + return m_downloads; +}; + + +KUrl DownloadManager::downloadDestination(const QString &filename) +{ + KUrl destination = ReKonfig::downloadDir(); + if (destination.isEmpty()) + destination = KGlobalSettings::downloadPath(); + destination.addPath(filename); + + if (!ReKonfig::downloadToDefaultDir()) + { + destination = KFileDialog::getSaveUrl(destination); + // if user canceled the download return empty url + if (destination.isEmpty()) + return KUrl(); + } + return destination; +} + + +void DownloadManager::slotDownloadFinished(int errorCode) +{ + Q_UNUSED(errorCode) + + // if sender exists and list contains it - (open and) delete it + Download *download = qobject_cast<Download *>(sender()); + if (download && m_downloads.contains(download)) + { + if (download->type() == Download::Open) + { + KSharedPtr<KMimeType> mimeType = KMimeType::findByPath(download->destUrl().prettyUrl()); + KRun::runUrl(download->destUrl(), mimeType->name(), NULL, true); + } + disconnect(download, SIGNAL(downloadFinished(int)), this, SLOT(slotDownloadFinished(int))); + int index = m_downloads.indexOf(download); + delete m_downloads.takeAt(index); + return; + } + kWarning() << "Could not find download or invalid sender. Sender:" << sender(); +} + + +//---- + +#include <KJob> +#include <KIO/Job> +#include <KIO/CopyJob> + + +Download::Download(const KUrl &srcUrl, const KUrl &destUrl, DownloadType type) : QObject() , m_srcUrl(srcUrl) , m_destUrl(destUrl) + , m_type(type) { - kWarning() << "DownloadFile: " << m_srcUrl.url() << " to dest: " << m_destUrl.url(); - m_copyJob = KIO::get(m_srcUrl); - connect(m_copyJob, SIGNAL(data(KIO::Job*, const QByteArray &)), SLOT(slotData(KIO::Job*, const QByteArray&))); + Q_ASSERT(!m_srcUrl.isEmpty()); + Q_ASSERT(!m_destUrl.isEmpty()); + kDebug() << "DownloadFile: " << m_srcUrl.url() << " to dest: " << m_destUrl.url(); + + m_copyJob = KIO::file_copy(m_srcUrl, m_destUrl); connect(m_copyJob, SIGNAL(result(KJob *)), SLOT(slotResult(KJob *))); } @@ -47,45 +186,38 @@ Download::~Download() } -void Download::slotData(KIO::Job *job, const QByteArray& data) +void Download::cancel() { - Q_UNUSED(job); - m_data.append(data); + bool result = m_copyJob->kill(KJob::EmitResult); + Q_ASSERT(result); } -void Download::slotResult(KJob * job) +void Download::slotResult(KJob *job) { switch (job->error()) { - case 0://The download has finished + case 0: //The download has finished { - kDebug(5001) << "Downloading successfully finished: " << m_destUrl.url(); - QFile destFile(m_destUrl.path()); - int n = 1; - QString fn = destFile.fileName(); - while (destFile.exists()) - { - destFile.setFileName(fn + "." + QString::number(n)); - n++; - } - if (destFile.open(QIODevice::WriteOnly | QIODevice::Text)) - { - destFile.write(m_data); - destFile.close(); - } - m_data = 0; + kDebug() << "Downloading successfully finished: " << m_destUrl.url(); break; } case KIO::ERR_FILE_ALREADY_EXIST: { kWarning() << "ERROR - File already exists"; - m_data = 0; + break; + } + case KIO::ERR_USER_CANCELED: + { + kWarning() << "ERROR - User canceled the downlaod"; break; } default: kWarning() << "We are sorry to say you, that there were errors while downloading :("; - m_data = 0; break; } + + // inform the world + emit downloadFinished(job->error()); } + diff --git a/src/download.h b/src/download.h index 001c90f3..7b7a5bbf 100644 --- a/src/download.h +++ b/src/download.h @@ -18,57 +18,113 @@ * * ============================================================ */ + #ifndef DOWNLOAD_H #define DOWNLOAD_H +// Auto Includes +#include "rekonq.h" + // KDE Includes -#include <KUrl> -#include <kio/job.h> +#include <KIO/FileCopyJob> // Qt Includes #include <QObject> -#include <QByteArray> + +// Forward Declarations +class KJob; + +namespace KIO +{ + class Job; +} + /** * This class lets rekonq to download an object from the network. * Creating a new object, you can continue downloading a file also * when rekonq is closed. * - * @author Lukas Appelhans <l.appelhans@gmx.de> - * @author Andrea Diamantini <adjam7@gmail.com> - * */ class Download : public QObject { Q_OBJECT + public: + enum DownloadType { Save, Open }; + /** * Class constructor. This is the unique method we need to * use this class. In fact Download class needs to know just * "where" catch the file to download and where it has to put it * * @param srcUrl the source url - * * @param destUrl the destination url * */ - Download(const KUrl &srcUrl, const KUrl &destUrl); + Download(const KUrl &srcUrl, const KUrl &destUrl, DownloadType type); /** * class destructor */ ~Download(); + KUrl srcUrl() const { return m_srcUrl; } + KUrl destUrl() const { return m_destUrl; } + DownloadType type() const { return m_type; } + void cancel(); + +signals: + void downloadFinished(int errorCode); + private slots: void slotResult(KJob *job); - void slotData(KIO::Job *job, const QByteArray& data); private: - KIO::TransferJob *m_copyJob; + KIO::FileCopyJob *m_copyJob; KUrl m_srcUrl; KUrl m_destUrl; KUrl m_destFile; QByteArray m_data; + DownloadType m_type; }; + +// ---------------------- + + +class DownloadManager : public QObject +{ + Q_OBJECT + +public: + DownloadManager(); + ~DownloadManager(); + + /** + * @short Creates new download job. + * This method lets you to download a file from a remote source url + * to a local destination url. + * + * @param srcUrl the source url + * @param destUrl the destination url (default value is your default download destination setting) + * + */ + void newDownload(const KUrl &srcUrl, const KUrl &destUrl = KUrl()); + + const QList<Download *> &downloads() const; + +public slots: + void slotDownloadFinished(int errorCode); + +private: + KUrl downloadDestination(const QString &filename); + + QList<Download *> m_downloads; +}; + + +//-- + + #endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9b04cbbd..8180b1e1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -36,6 +36,7 @@ #include "webview.h" #include "mainview.h" #include "bookmarks.h" +#include "download.h" // KDE Includes #include <KUrl> @@ -51,6 +52,7 @@ #include <KMenu> #include <KGlobalSettings> #include <KPushButton> +#include <KTemporaryFile> // Qt Includes @@ -428,9 +430,7 @@ void MainWindow::slotOpenLocation() void MainWindow::slotFileSaveAs() { KUrl srcUrl = currentTab()->url(); - QString destPath = KFileDialog::getSaveFileName(); - KUrl destUrl = KUrl(destPath); - Application::instance()->downloadUrl(srcUrl, destUrl); + Application::downloadManager()->newDownload(srcUrl); } @@ -492,6 +492,7 @@ void MainWindow::slotFileOpen() } +// TODO: Port to KDE void MainWindow::slotFilePrintPreview() { if (!currentTab()) @@ -510,6 +511,7 @@ void MainWindow::slotFilePrint() } +// TODO: Port to KDE void MainWindow::printRequested(QWebFrame *frame) { QPrinter printer; @@ -684,8 +686,6 @@ void MainWindow::slotViewPageSource() KRun::runUrl(url, QLatin1String("text/plain"), this, isTempFile); } -} - void MainWindow::slotHome() { diff --git a/src/rekonq.kcfg b/src/rekonq.kcfg index a7b7f848..a02f10ad 100644 --- a/src/rekonq.kcfg +++ b/src/rekonq.kcfg @@ -17,6 +17,9 @@ <entry name="downloadDir" type="Path"> <default>$HOME</default> </entry> + <entry name="downloadToDefaultDir" type="Bool"> + <default>false</default> + </entry> <entry name="alwaysShowTabBar" type="Bool"> <default>true</default> </entry> diff --git a/src/settings_general.ui b/src/settings_general.ui index 4d47ef4b..3b117854 100644 --- a/src/settings_general.ui +++ b/src/settings_general.ui @@ -77,6 +77,13 @@ </property> </widget> </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="kcfg_downloadToDefaultDir"> + <property name="text"> + <string>ask where saving downloads</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/webview.cpp b/src/webview.cpp index 004a4642..91a5b988 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -194,7 +194,7 @@ void WebPage::handleUnsupportedContent(QNetworkReply *reply) KUrl srcUrl = reply->url(); QString path = ReKonfig::downloadDir() + QString("/") + srcUrl.fileName(); KUrl destUrl = KUrl(path); - Application::instance()->downloadUrl(srcUrl, destUrl); + Application::downloadManager()->newDownload(srcUrl); return; } @@ -387,7 +387,7 @@ void WebView::downloadRequested(const QNetworkRequest &request) KUrl srcUrl = request.url(); QString path = ReKonfig::downloadDir() + QString("/") + srcUrl.fileName(); KUrl destUrl = KUrl(path); - Application::instance()->downloadUrl(srcUrl, destUrl); + Application::downloadManager()->newDownload(srcUrl); } |