From: lvaatamoinen Date: Thu, 19 Nov 2009 13:55:50 +0000 (+0000) Subject: - DownloadManager code in place X-Git-Url: http://git.maemo.org/git/?p=qtrapids;a=commitdiff_plain;h=5032546701da06d7307fc543d74be93e5319c350 - DownloadManager code in place - Torrents can be downloaded and added via Search plugin - TODO: Search engine descriptions and parser git-svn-id: file:///svnroot/qtrapids/trunk@39 42ac0dd5-4c8c-4c71-bb3e-ecdfe252ffda --- diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 7eca355..884ced0 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -27,7 +27,7 @@ #include #include #include - +#include #include "DownloadView.h" #include "SeedView.h" @@ -160,11 +160,38 @@ void MainWindow::addMenuItem(QWidget* widget, PluginWidgetType type) { } +bool MainWindow::eventRequest(QVariant param, PluginRequest req) +{ + if (req == qtrapids::PluginHostInterface::OPEN_FILE) { + QString sourceFile = param.toString(); + + // Get the source files name from the full path: + QFileInfo fInfo(sourceFile); + QString targetFile = fInfo.fileName(); + targetFile = settings_.value("download/directory").toString() + targetFile; + + // Copy temoporary file to Downloads directory... + if (!QFile::copy(sourceFile, targetFile)) { + qDebug() << "File copying failed"; + return false; + } else { + // If copying was successful, remove the original temporary file. + QFile::remove(sourceFile); + } + + // ...and start the torrent: + on_torrentFileSelected(targetFile); + } + + return true; +} + + //=========================== PRIVATE ================================ void MainWindow::LoadPlugins() { - /// @todo get plugin directory from settings or go through multiple diectories + /// @todo get plugin directory from settings or go through multiple directories /// Now we only check the application directory pluginsDir_ = QDir(qApp->applicationDirPath()); pluginsDir_.cd("plugins"); @@ -207,7 +234,6 @@ void MainWindow::on_openAction_clicked() dialog->setFileMode(QFileDialog::ExistingFile); connect(dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(on_torrentFileSelected(const QString&))); dialog->show(); - } void MainWindow::on_removeAction_clicked() diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 715ce23..4094a50 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -45,12 +45,13 @@ class MainWindow : public QMainWindow, public qtrapids::PluginHostInterface { virtual ~MainWindow(); // Implemented from PluginHostInterface - virtual bool setGui(QWidget* widget, PluginWidgetType type = UNKNOWN); - virtual void addPluginWidget(QWidget* widget, PluginWidgetType type = UNKNOWN); - virtual void addToolbar(QWidget* widget, PluginWidgetType type = UNKNOWN); - virtual void addToolItem(QWidget* widget, PluginWidgetType type = UNKNOWN); - virtual void addMenu(QWidget* widget, PluginWidgetType type = UNKNOWN); - virtual void addMenuItem(QWidget* widget, PluginWidgetType type = UNKNOWN); + virtual bool setGui(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual void addPluginWidget(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual void addToolbar(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual void addToolItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual void addMenu(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual void addMenuItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE); + virtual bool eventRequest(QVariant param, PluginRequest req = UNKNOWN_REQUEST); signals: void itemSelected(bool enabled); diff --git a/src/plugins/PluginInterface.h b/src/plugins/PluginInterface.h index 33cd491..d5ed6c8 100644 --- a/src/plugins/PluginInterface.h +++ b/src/plugins/PluginInterface.h @@ -21,7 +21,8 @@ #define PLUGININTERFACE_H #include -#include +#include +//#include namespace qtrapids { @@ -44,23 +45,37 @@ namespace qtrapids enum PluginWidgetType { BASE_WIDGET, TAB_PAGE, - UNKNOWN + UNKNOWN_TYPE + }; + + /// @enum PluginRequest for requesting host application functionality + /// E.g. open torrent file etc. + /// @todo Additional functionality request constants. + enum PluginRequest { + OPEN_FILE, + UNKNOWN_REQUEST }; /// @brief Sets the plugin GUI element to host application /// @note It is up to the host application to decide how to manage /// and show the actual widget. - virtual bool setGui(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; + virtual bool setGui(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; /// @brief Adds additional plugin wigdets to the host application. /// This functio can be called by the plugin recursively, i.e. when GUI events occur /// The host application must handle placing the additional widgets. /// @todo Could we implement this using in a more manageable way, e.g. signal-slot? - virtual void addPluginWidget(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; - virtual void addToolbar(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; - virtual void addToolItem(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; - virtual void addMenu(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; - virtual void addMenuItem(QWidget* widget, PluginWidgetType type = UNKNOWN) = 0; + virtual void addPluginWidget(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; + virtual void addToolbar(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; + virtual void addToolItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; + virtual void addMenu(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; + virtual void addMenuItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE) = 0; + + /// @brief Plugin can request to host application functionality. + /// Host application defines the service policy for plugin requests. + /// @todo Sending events would benefit from Qt signal, how to define + /// signal in an abstract interface? + virtual bool eventRequest(QVariant param, PluginRequest req = UNKNOWN_REQUEST) = 0; }; diff --git a/src/plugins/searchplugin/DownloadManager.cpp b/src/plugins/searchplugin/DownloadManager.cpp new file mode 100644 index 0000000..01e2cb4 --- /dev/null +++ b/src/plugins/searchplugin/DownloadManager.cpp @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lassi Väätämöinen * + * lassi.vaatamoinen@ixonos.com * + * * + * 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) any later version. * + * * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "DownloadManager.h" + + +DownloadManager::DownloadManager(QObject *parent) : + QObject(parent) // Superclass construct +{ +} + +DownloadManager::DownloadManager(QUrl url, QString outfile, QObject *parent) : + QObject(parent), // Superclass construct + url_(url), + filepath_(outfile), + file_(QString(outfile)) +{ + file_.open(QIODevice::WriteOnly); +} + + +DownloadManager::~DownloadManager() +{ + file_.close(); + delete reply_; reply_ = NULL; +} + + +void DownloadManager::start() +{ + reply_ = manager_.get(QNetworkRequest(url_)); + + connect(reply_, SIGNAL(readyRead()), this, SLOT(on_readyRead())); + connect(reply_, SIGNAL(downloadProgress (qint64 , qint64)), SLOT(on_downloadProgress(qint64, qint64))); + connect(reply_, SIGNAL(finished()), this, SLOT(on_replyFinished())); +} + + +void DownloadManager::on_readyRead() +{ + //qDebug() << "on_readyRead()"; + WriteToFile(); +} + +void DownloadManager::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + static double last = 0; + + double prog = static_cast(bytesReceived) / static_cast(bytesTotal); + if ((prog-last) >= 0.01) { + last = prog; + emit progress(static_cast(100*prog)); + } else if (bytesReceived == bytesTotal) { + emit progress(100); + } + +} + +void DownloadManager::on_replyFinished() +{ + WriteToFile(); + file_.close(); + emit finished(filepath_); +} + + +void DownloadManager::WriteToFile() +{ + QByteArray readData = reply_->readAll(); + + if (readData.isEmpty()) { + qDebug() << "on_replyFinished(): No data available for reading"; + } else { + file_.write(readData); + /// @todo check file_.error() + } +} diff --git a/src/plugins/searchplugin/DownloadManager.h b/src/plugins/searchplugin/DownloadManager.h new file mode 100644 index 0000000..f95a3d0 --- /dev/null +++ b/src/plugins/searchplugin/DownloadManager.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lassi Väätämöinen * + * lassi.vaatamoinen@ixonos.com * + * * + * 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) any later version. * + * * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DOWNLOADMANAGER_H +#define DOWNLOADMANAGER_H + + +#include +#include +#include +#include +#include + + +class DownloadManager : public QObject +{ + Q_OBJECT + + public: + DownloadManager(QObject *parent = NULL); + DownloadManager(QUrl url, QString outfile, QObject *parent = NULL); + virtual ~DownloadManager(); + virtual void start(); + void setUrl(QUrl url); + void setFilepath(QString filepath); + + public slots: + void on_readyRead(); + void on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void on_replyFinished(); + + signals: + void progress(int prog); + void finished(QString filepath); + + private: + void WriteToFile(); + + private: + QNetworkAccessManager manager_; + QUrl url_; + QNetworkReply *reply_; + QString filepath_; + QFile file_; +}; + +#endif diff --git a/src/plugins/searchplugin/SearchPlugin.cpp b/src/plugins/searchplugin/SearchPlugin.cpp index 27417f1..55e104e 100644 --- a/src/plugins/searchplugin/SearchPlugin.cpp +++ b/src/plugins/searchplugin/SearchPlugin.cpp @@ -26,19 +26,24 @@ #include #include #include +#include #include - +#include #include "SearchPlugin.h" +#include "DownloadManager.h" namespace qtrapids { SearchPlugin::SearchPlugin() : - comboBox_(NULL), searchLine_(NULL), searchButton_(NULL), host_(NULL) + comboBox_(NULL), searchLine_(NULL), + searchButton_(NULL), result_(NULL), + dlManager_(NULL), host_(NULL) { - // TODO: Parse engine descriptions. - // -Add engines to model + // TODO: Parse search engine XML(?) descriptions. + // -Add search engines to model // -Show model in comboBox + // Add back/forward/refresh -buttons to widget to allow some browsing } @@ -47,7 +52,6 @@ namespace qtrapids host_ = host; if (host_ != NULL) { - QWidget *pluginWidget = new QWidget; QVBoxLayout *vbox = new QVBoxLayout; QHBoxLayout *hbox = new QHBoxLayout; @@ -73,17 +77,35 @@ namespace qtrapids return NULL; } + void SearchPlugin::on_searchButton_clicked() { QUrl searchUrl(QString("http://www.google.fi/search?q=" + searchLine_->text())); qDebug() << searchUrl; - QWebView *result = new QWebView; - result->load(searchUrl); + result_ = new QWebView; + + // Get underlying QWebPage and change link delegation, so we can meddle with links in on_linkClicked(). + QWebPage *resultPage = result_->page(); + resultPage->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks); + + connect(resultPage, SIGNAL(linkClicked(const QUrl&)), this, SLOT(on_linkClicked(const QUrl&))); + connect(result_, SIGNAL(loadFinished(bool)), this, SLOT(on_loadFinished(bool))); + + result_->load(searchUrl); - on_searchResult((QWidget*)result); + on_searchResult((QWidget*)result_); + } + + + void SearchPlugin::on_loadFinished(bool ok) + { + if (ok) { + qDebug() << "on_loadFinished()"; + } } + void SearchPlugin::on_searchResult(QWidget* resultWidget) { qDebug() << "on_searchResult()"; @@ -92,6 +114,45 @@ namespace qtrapids } } + void SearchPlugin::on_linkClicked(const QUrl& url) + { + // Get the path part of URL (the part after the host part) + QString path = url.path(); + QFileInfo fInfo(path); + + // Check path suffix. If it is .torrent, we should download: + /// @todo We should also check MIME-type, instead of relying on file suffix. + /// @todo Also, after downloading, the torrent bencoding validity should be checked at plugin host.. + if (fInfo.suffix() == "torrent") { + qDebug() << "IS TORRENT"; + QString filename = fInfo.fileName(); + + // Destroy ongoing download, if any. + if (dlManager_) { + delete dlManager_; + dlManager_ = NULL; + } + + // Start downloading Torrent file. + dlManager_ = new DownloadManager(url, "/tmp/" + filename); + connect(dlManager_, SIGNAL(finished(QString)), this, SLOT(on_downloadFinished(QString))); + dlManager_->start(); + } else { + // If was not .torrent -file, check URL validity and load the page as usual. + if (url.isValid()) { + result_->load(url); + } + } + } + + void SearchPlugin::on_downloadFinished(QString filepath) + { + qDebug() << "TORRENT DOWNLOADED: " << filepath; + delete dlManager_; + dlManager_ = NULL; + host_->eventRequest(QVariant(filepath), qtrapids::PluginHostInterface::OPEN_FILE); + } + } // namespace qtrapids Q_EXPORT_PLUGIN2(searchplugin, qtrapids::SearchPlugin) diff --git a/src/plugins/searchplugin/SearchPlugin.h b/src/plugins/searchplugin/SearchPlugin.h index ff709b2..0b6a158 100644 --- a/src/plugins/searchplugin/SearchPlugin.h +++ b/src/plugins/searchplugin/SearchPlugin.h @@ -29,6 +29,8 @@ class QWidget; class QComboBox; class QPushButton; class QLineEdit; +class QWebView; +class DownloadManager; namespace qtrapids { @@ -49,11 +51,15 @@ signals: private slots: void on_searchButton_clicked(); void on_searchResult(QWidget* resultWidget); - + void on_loadFinished(bool ok); + void on_linkClicked(const QUrl& url); + void on_downloadFinished(QString filepath); private: QComboBox *comboBox_; QLineEdit *searchLine_; QPushButton *searchButton_; + QWebView *result_; // Do not delete, plugin host takes ownership + DownloadManager *dlManager_; PluginHostInterface* host_; }; diff --git a/src/plugins/searchplugin/searchplugin.pro b/src/plugins/searchplugin/searchplugin.pro index 374ff9f..fea3cbe 100644 --- a/src/plugins/searchplugin/searchplugin.pro +++ b/src/plugins/searchplugin/searchplugin.pro @@ -1,7 +1,7 @@ ###################################################################### # Automatically generated by qmake (2.01a) Tue Nov 17 15:43:08 2009 ###################################################################### -QT += webkit +QT += webkit network TEMPLATE = lib @@ -16,5 +16,5 @@ DEPENDPATH += . .. INCLUDEPATH += . .. # Input -HEADERS += SearchPlugin.h -SOURCES += SearchPlugin.cpp +HEADERS += SearchPlugin.h DownloadManager.h +SOURCES += SearchPlugin.cpp DownloadManager.cpp