#include <QFileDialog>
#include <QMessageBox>
#include <QApplication>
-
+#include <QPluginLoader>
#include "DownloadView.h"
#include "SeedView.h"
{
}
+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");
dialog->setFileMode(QFileDialog::ExistingFile);
connect(dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(on_torrentFileSelected(const QString&)));
dialog->show();
-
}
void MainWindow::on_removeAction_clicked()
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);
#define PLUGININTERFACE_H
#include <QObject>
-#include <QPluginLoader>
+#include <QVariant>
+//#include <QPluginLoader>
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;
};
--- /dev/null
+/***************************************************************************
+ * 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()
+ }
+}
--- /dev/null
+/***************************************************************************
+ * 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
#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
}
host_ = host;
if (host_ != NULL) {
-
QWidget *pluginWidget = new QWidget;
QVBoxLayout *vbox = new QVBoxLayout;
QHBoxLayout *hbox = new QHBoxLayout;
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()";
}
}
+ 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)
class QComboBox;
class QPushButton;
class QLineEdit;
+class QWebView;
+class DownloadManager;
namespace qtrapids
{
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_;
};
######################################################################
# Automatically generated by qmake (2.01a) Tue Nov 17 15:43:08 2009
######################################################################
-QT += webkit
+QT += webkit network
TEMPLATE = lib
INCLUDEPATH += . ..
# Input
-HEADERS += SearchPlugin.h
-SOURCES += SearchPlugin.cpp
+HEADERS += SearchPlugin.h DownloadManager.h
+SOURCES += SearchPlugin.cpp DownloadManager.cpp