- DownloadManager code in place
authorlvaatamoinen <lassi.vaatamoinen@ixonos.com>
Thu, 19 Nov 2009 13:55:50 +0000 (13:55 +0000)
committerlvaatamoinen <lassi.vaatamoinen@ixonos.com>
Thu, 19 Nov 2009 13:55:50 +0000 (13:55 +0000)
- 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

src/gui/MainWindow.cpp
src/gui/MainWindow.h
src/plugins/PluginInterface.h
src/plugins/searchplugin/DownloadManager.cpp [new file with mode: 0644]
src/plugins/searchplugin/DownloadManager.h [new file with mode: 0644]
src/plugins/searchplugin/SearchPlugin.cpp
src/plugins/searchplugin/SearchPlugin.h
src/plugins/searchplugin/searchplugin.pro

index 7eca355..884ced0 100644 (file)
@@ -27,7 +27,7 @@
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QApplication>
-
+#include <QPluginLoader>
 
 #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()
index 715ce23..4094a50 100644 (file)
@@ -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);
index 33cd491..d5ed6c8 100644 (file)
@@ -21,7 +21,8 @@
 #define PLUGININTERFACE_H
 
 #include <QObject>
-#include <QPluginLoader>
+#include <QVariant>
+//#include <QPluginLoader>
 
 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 (file)
index 0000000..01e2cb4
--- /dev/null
@@ -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 <QDebug>
+
+#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<double>(bytesReceived) / static_cast<double>(bytesTotal);
+       if ((prog-last) >= 0.01) {
+               last = prog;
+               emit progress(static_cast<int>(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 (file)
index 0000000..f95a3d0
--- /dev/null
@@ -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 <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QUrl>
+#include <QFile>
+
+
+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
index 27417f1..55e104e 100644 (file)
 #include <QLineEdit>
 #include <QPushButton>
 #include <QUrl>
+#include <QFileInfo>
 #include <QWebView>
-
+#include <QWebPage>
 
 #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)
index ff709b2..0b6a158 100644 (file)
@@ -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_;
 
 };
index 374ff9f..fea3cbe 100644 (file)
@@ -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