Merge pull request #2892 from glassez/bittorrent

Core classes redesign (Issue #2433).
This commit is contained in:
sledgehammer999
2015-06-11 23:54:05 +03:00
207 changed files with 15273 additions and 13581 deletions

View File

@@ -29,13 +29,14 @@
*/
#include "engineselectdlg.h"
#include "downloadthread.h"
#include "fs_utils.h"
#include "misc.h"
#include "core/net/downloadmanager.h"
#include "core/net/downloadhandler.h"
#include "core/utils/fs.h"
#include "core/utils/misc.h"
#include "ico.h"
#include "searchengine.h"
#include "pluginsource.h"
#include "iconprovider.h"
#include "guiiconprovider.h"
#include "autoexpandabledialog.h"
#include <QProcess>
#include <QHeaderView>
@@ -47,7 +48,7 @@
#include <QMimeData>
enum EngineColumns {ENGINE_NAME, ENGINE_URL, ENGINE_STATE, ENGINE_ID};
const QString UPDATE_URL = QString("https://raw.github.com/qbittorrent/qBittorrent/master/src/searchengine/") + (misc::pythonVersion() >= 3 ? "nova3" : "nova") + "/engines/";
const QString UPDATE_URL = QString("https://raw.github.com/qbittorrent/qBittorrent/master/src/searchengine/") + (Utils::Misc::pythonVersion() >= 3 ? "nova3" : "nova") + "/engines/";
engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_engines) : QDialog(parent), supported_engines(supported_engines) {
setupUi(this);
@@ -55,12 +56,9 @@ engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_en
pluginsTree->header()->resizeSection(0, 170);
pluginsTree->header()->resizeSection(1, 220);
pluginsTree->hideColumn(ENGINE_ID);
actionUninstall->setIcon(IconProvider::instance()->getIcon("list-remove"));
actionUninstall->setIcon(GuiIconProvider::instance()->getIcon("list-remove"));
connect(actionEnable, SIGNAL(toggled(bool)), this, SLOT(enableSelection(bool)));
connect(pluginsTree, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContextMenu(const QPoint&)));
downloader = new DownloadThread(this);
connect(downloader, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
loadSupportedSearchEngines();
connect(supported_engines, SIGNAL(newSupportedEngine(QString)), this, SLOT(addNewEngine(QString)));
connect(pluginsTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(toggleEngineState(QTreeWidgetItem*, int)));
@@ -70,8 +68,6 @@ engineSelectDlg::engineSelectDlg(QWidget *parent, SupportedEngines *supported_en
engineSelectDlg::~engineSelectDlg() {
qDebug("Destroying engineSelectDlg");
emit enginesChanged();
qDebug("Before deleting downloader");
delete downloader;
qDebug("Engine plugins dialog destroyed");
}
@@ -80,15 +76,15 @@ void engineSelectDlg::dropEvent(QDropEvent *event) {
QStringList files = event->mimeData()->text().split(QString::fromUtf8("\n"));
foreach (QString file, files) {
qDebug("dropped %s", qPrintable(file));
if (misc::isUrl(file)) {
if (Utils::Misc::isUrl(file)) {
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(file);
downloadFromUrl(file);
continue;
}
if (file.endsWith(".py", Qt::CaseInsensitive)) {
if (file.startsWith("file:", Qt::CaseInsensitive))
file = QUrl(file).toLocalFile();
QString plugin_name = fsutils::fileName(file);
QString plugin_name = Utils::Fs::fileName(file);
plugin_name.chop(3); // Remove extension
installPlugin(file, plugin_name);
}
@@ -109,7 +105,7 @@ void engineSelectDlg::dragEnterEvent(QDragEnterEvent *event) {
void engineSelectDlg::on_updateButton_clicked() {
// Download version file from update server on sourceforge
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(QString(UPDATE_URL)+"versions.txt");
downloadFromUrl(QString(UPDATE_URL) + "versions.txt");
}
void engineSelectDlg::toggleEngineState(QTreeWidgetItem *item, int) {
@@ -159,7 +155,7 @@ void engineSelectDlg::on_actionUninstall_triggered() {
}else {
// Proceed with uninstall
// remove it from hard drive
QDir enginesFolder(fsutils::searchEngineLocation() + "/engines");
QDir enginesFolder(Utils::Fs::searchEngineLocation() + "/engines");
QStringList filters;
filters << id+".*";
QStringList files = enginesFolder.entryList(filters, QDir::Files, QDir::Unsorted);
@@ -225,7 +221,7 @@ QTreeWidgetItem* engineSelectDlg::findItemWithID(QString id) {
}
bool engineSelectDlg::isUpdateNeeded(QString plugin_name, qreal new_version) const {
qreal old_version = SearchEngine::getPluginVersion(fsutils::searchEngineLocation() + "/engines/" + plugin_name + ".py");
qreal old_version = SearchEngine::getPluginVersion(Utils::Fs::searchEngineLocation() + "/engines/" + plugin_name + ".py");
qDebug("IsUpdate needed? tobeinstalled: %.2f, alreadyinstalled: %.2f", new_version, old_version);
return (new_version > old_version);
}
@@ -240,13 +236,13 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
return;
}
// Process with install
QString dest_path = fsutils::searchEngineLocation() + "/engines/" + plugin_name + ".py";
QString dest_path = Utils::Fs::searchEngineLocation() + "/engines/" + plugin_name + ".py";
bool update = false;
if (QFile::exists(dest_path)) {
// Backup in case install fails
QFile::copy(dest_path, dest_path+".bak");
fsutils::forceRemove(dest_path);
fsutils::forceRemove(dest_path+"c");
Utils::Fs::forceRemove(dest_path);
Utils::Fs::forceRemove(dest_path+"c");
update = true;
}
// Copy the plugin
@@ -257,22 +253,22 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) {
if (!supported_engines->contains(plugin_name)) {
if (update) {
// Remove broken file
fsutils::forceRemove(dest_path);
Utils::Fs::forceRemove(dest_path);
// restore backup
QFile::copy(dest_path+".bak", dest_path);
fsutils::forceRemove(dest_path+".bak");
Utils::Fs::forceRemove(dest_path+".bak");
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name));
return;
} else {
// Remove broken file
fsutils::forceRemove(dest_path);
Utils::Fs::forceRemove(dest_path);
QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name));
return;
}
}
// Install was successful, remove backup
if (update) {
fsutils::forceRemove(dest_path+".bak");
Utils::Fs::forceRemove(dest_path+".bak");
}
if (update) {
QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name));
@@ -305,17 +301,17 @@ void engineSelectDlg::addNewEngine(QString engine_name) {
setRowColor(pluginsTree->indexOfTopLevelItem(item), "red");
}
// Handle icon
QString iconPath = fsutils::searchEngineLocation() + "/engines/" + engine->getName() + ".png";
QString iconPath = Utils::Fs::searchEngineLocation() + "/engines/" + engine->getName() + ".png";
if (QFile::exists(iconPath)) {
// Good, we already have the icon
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
} else {
iconPath = fsutils::searchEngineLocation() + "/engines/" + engine->getName() + ".ico";
iconPath = Utils::Fs::searchEngineLocation() + "/engines/" + engine->getName() + ".ico";
if (QFile::exists(iconPath)) { // ICO support
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
} else {
// Icon is missing, we must download it
downloader->downloadUrl(engine->getUrl()+"/favicon.ico");
downloadFromUrl(engine->getUrl() + "/favicon.ico");
}
}
}
@@ -346,7 +342,7 @@ void engineSelectDlg::askForPluginUrl() {
}
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(url);
downloadFromUrl(url);
}
void engineSelectDlg::askForLocalPlugin() {
@@ -392,8 +388,8 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
qDebug("Plugin: %s is outdated", qPrintable(plugin_name));
// Downloading update
setCursor(QCursor(Qt::WaitCursor));
downloader->downloadUrl(UPDATE_URL+plugin_name+".py");
//downloader->downloadUrl(UPDATE_URL+plugin_name+".png");
downloadFromUrl(UPDATE_URL + plugin_name + ".py");
//downloadFromUrl(UPDATE_URL + plugin_name + ".png");
updated = true;
}else {
qDebug("Plugin: %s is up to date", qPrintable(plugin_name));
@@ -402,15 +398,22 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
// Close file
versions.close();
// Clean up tmp file
fsutils::forceRemove(versions_file);
Utils::Fs::forceRemove(versions_file);
if (file_correct && !updated) {
QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date."));
}
return file_correct;
}
void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
filePath = fsutils::fromNativePath(filePath);
void engineSelectDlg::downloadFromUrl(const QString &url)
{
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
}
void engineSelectDlg::processDownloadedFile(const QString &url, QString filePath) {
filePath = Utils::Fs::fromNativePath(filePath);
setCursor(QCursor(Qt::ArrowCursor));
qDebug("engineSelectDlg received %s", qPrintable(url));
if (url.endsWith("favicon.ico", Qt::CaseInsensitive)) {
@@ -425,34 +428,34 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) {
QFile icon(filePath);
icon.open(QIODevice::ReadOnly);
if (ICOHandler::canRead(&icon))
iconPath = fsutils::searchEngineLocation() + "/engines/" + id + ".ico";
iconPath = Utils::Fs::searchEngineLocation() + "/engines/" + id + ".ico";
else
iconPath = fsutils::searchEngineLocation() + "/engines/" + id + ".png";
iconPath = Utils::Fs::searchEngineLocation() + "/engines/" + id + ".png";
QFile::copy(filePath, iconPath);
item->setData(ENGINE_NAME, Qt::DecorationRole, QVariant(QIcon(iconPath)));
}
}
// Delete tmp file
fsutils::forceRemove(filePath);
Utils::Fs::forceRemove(filePath);
return;
}
if (url.endsWith("versions.txt")) {
if (!parseVersionsFile(filePath)) {
QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable."));
}
fsutils::forceRemove(filePath);
Utils::Fs::forceRemove(filePath);
return;
}
if (url.endsWith(".py", Qt::CaseInsensitive)) {
QString plugin_name = fsutils::fileName(url);
QString plugin_name = Utils::Fs::fileName(url);
plugin_name.chop(3); // Remove extension
installPlugin(filePath, plugin_name);
fsutils::forceRemove(filePath);
Utils::Fs::forceRemove(filePath);
return;
}
}
void engineSelectDlg::handleDownloadFailure(QString url, QString reason) {
void engineSelectDlg::handleDownloadFailure(const QString &url, const QString &reason) {
setCursor(QCursor(Qt::ArrowCursor));
if (url.endsWith("favicon.ico", Qt::CaseInsensitive)) {
qDebug("Could not download favicon: %s, reason: %s", qPrintable(url), qPrintable(reason));

View File

@@ -34,8 +34,6 @@
#include "ui_engineselect.h"
#include "supportedengines.h"
class DownloadThread;
QT_BEGIN_NAMESPACE
class QDropEvent;
QT_END_NAMESPACE
@@ -44,7 +42,8 @@ class engineSelectDlg : public QDialog, public Ui::engineSelect{
Q_OBJECT
private:
DownloadThread *downloader;
void downloadFromUrl(const QString &url);
SupportedEngines *supported_engines;
public:
@@ -66,8 +65,8 @@ class engineSelectDlg : public QDialog, public Ui::engineSelect{
void addNewEngine(QString engine_name);
void toggleEngineState(QTreeWidgetItem*, int);
void setRowColor(int row, QString color);
void processDownloadedFile(QString url, QString filePath);
void handleDownloadFailure(QString url, QString reason);
void processDownloadedFile(const QString &url, QString filePath);
void handleDownloadFailure(const QString &url, const QString &reason);
void displayContextMenu(const QPoint& pos);
void enableSelection(bool enable);
void on_actionUninstall_triggered();

View File

@@ -48,13 +48,14 @@
#endif
#include "searchengine.h"
#include "qbtsession.h"
#include "fs_utils.h"
#include "misc.h"
#include "preferences.h"
#include "core/bittorrent/session.h"
#include "core/utils/fs.h"
#include "core/utils/misc.h"
#include "core/preferences.h"
#include "searchlistdelegate.h"
#include "mainwindow.h"
#include "iconprovider.h"
#include "addnewtorrentdialog.h"
#include "guiiconprovider.h"
#include "lineedit.h"
#define SEARCHHISTORY_MAXSIZE 50
@@ -69,10 +70,10 @@ SearchEngine::SearchEngine(MainWindow* parent)
searchBarLayout->insertWidget(0, search_pattern);
connect(search_pattern, SIGNAL(returnPressed()), search_button, SLOT(click()));
// Icons
search_button->setIcon(IconProvider::instance()->getIcon("edit-find"));
download_button->setIcon(IconProvider::instance()->getIcon("download"));
goToDescBtn->setIcon(IconProvider::instance()->getIcon("application-x-mswinurl"));
enginesButton->setIcon(IconProvider::instance()->getIcon("preferences-system-network"));
search_button->setIcon(GuiIconProvider::instance()->getIcon("edit-find"));
download_button->setIcon(GuiIconProvider::instance()->getIcon("download"));
goToDescBtn->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl"));
enginesButton->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network"));
tabWidget->setTabsClosable(true);
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
// Boolean initialization
@@ -216,7 +217,7 @@ void SearchEngine::on_search_button_clicked() {
// Getting checked search engines
QStringList params;
search_stopped = false;
params << fsutils::toNativePath(fsutils::searchEngineLocation() + "/nova2.py");
params << Utils::Fs::toNativePath(Utils::Fs::searchEngineLocation() + "/nova2.py");
if (selectedEngine() == "all") params << supported_engines->enginesAll().join(",");
else if (selectedEngine() == "enabled") params << supported_engines->enginesEnabled().join(",");
else if (selectedEngine() == "multi") params << supported_engines->enginesEnabled().join(",");
@@ -254,7 +255,7 @@ void SearchEngine::saveResultsColumnsWidth() {
void SearchEngine::downloadTorrent(QString engine_url, QString torrent_url) {
if (torrent_url.startsWith("bc://bt/", Qt::CaseInsensitive)) {
qDebug("Converting bc link to magnet link");
torrent_url = misc::bcLinkToMagnet(torrent_url);
torrent_url = Utils::Misc::bcLinkToMagnet(torrent_url);
}
qDebug() << Q_FUNC_INFO << torrent_url;
if (torrent_url.startsWith("magnet:")) {
@@ -267,7 +268,7 @@ void SearchEngine::downloadTorrent(QString engine_url, QString torrent_url) {
connect(downloadProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(downloadFinished(int,QProcess::ExitStatus)));
downloaders << downloadProcess;
QStringList params;
params << fsutils::toNativePath(fsutils::searchEngineLocation() + "/nova2dl.py");
params << Utils::Fs::toNativePath(Utils::Fs::searchEngineLocation() + "/nova2dl.py");
params << engine_url;
params << torrent_url;
// Launch search
@@ -308,8 +309,11 @@ void SearchEngine::downloadFinished(int exitcode, QProcess::ExitStatus) {
QStringList parts = line.split(' ');
if (parts.size() == 2) {
QString path = parts[0];
QString url = parts[1];
QBtSession::instance()->processDownloadedFile(url, path);
if (Preferences::instance()->useAdditionDialog())
AddNewTorrentDialog::show(path, mp_mainWindow);
else
BitTorrent::Session::instance()->addTorrent(path);
}
}
qDebug("Deleting downloadProcess");
@@ -319,16 +323,16 @@ void SearchEngine::downloadFinished(int exitcode, QProcess::ExitStatus) {
static void removePythonScriptIfExists(const QString& script_path)
{
fsutils::forceRemove(script_path);
fsutils::forceRemove(script_path + "c");
Utils::Fs::forceRemove(script_path);
Utils::Fs::forceRemove(script_path + "c");
}
// Update nova.py search plugin if necessary
void SearchEngine::updateNova() {
qDebug("Updating nova");
// create nova directory if necessary
QDir search_dir(fsutils::searchEngineLocation());
QString nova_folder = misc::pythonVersion() >= 3 ? "nova3" : "nova";
QDir search_dir(Utils::Fs::searchEngineLocation());
QString nova_folder = Utils::Misc::pythonVersion() >= 3 ? "nova3" : "nova";
QFile package_file(search_dir.absoluteFilePath("__init__.py"));
package_file.open(QIODevice::WriteOnly | QIODevice::Text);
package_file.close();
@@ -378,7 +382,7 @@ void SearchEngine::updateNova() {
removePythonScriptIfExists(filePath);
QFile::copy(":/"+nova_folder+"/sgmllib3.py", filePath);
}
QDir destDir(QDir(fsutils::searchEngineLocation()).absoluteFilePath("engines"));
QDir destDir(QDir(Utils::Fs::searchEngineLocation()).absoluteFilePath("engines"));
QDir shipped_subDir(":/"+nova_folder+"/engines/");
QStringList files = shipped_subDir.entryList();
foreach (const QString &file, files) {

View File

@@ -36,7 +36,7 @@
#include <QModelIndex>
#include <QPainter>
#include <QProgressBar>
#include "misc.h"
#include "core/utils/misc.h"
#include "searchengine.h"
class SearchListDelegate: public QItemDelegate {
@@ -53,7 +53,7 @@ class SearchListDelegate: public QItemDelegate {
switch(index.column()) {
case SearchSortModel::SIZE:
QItemDelegate::drawBackground(painter, opt, index);
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
break;
default:
QItemDelegate::paint(painter, option, index);

View File

@@ -2,7 +2,7 @@
#define SEARCHSORTMODEL_H
#include <QSortFilterProxyModel>
#include "misc.h"
#include "core/utils/string.h"
class SearchSortModel : public QSortFilterProxyModel {
Q_OBJECT
@@ -23,7 +23,7 @@ protected:
Q_ASSERT(vR.isValid());
bool res = false;
if (misc::naturalSort(vL.toString(), vR.toString(), res))
if (Utils::String::naturalSort(vL.toString(), vR.toString(), res))
return res;
return QSortFilterProxyModel::lessThan(left, right);

View File

@@ -36,9 +36,9 @@
#include "searchtab.h"
#include "searchlistdelegate.h"
#include "misc.h"
#include "core/utils/misc.h"
#include "searchengine.h"
#include "preferences.h"
#include "core/preferences.h"
SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
{

View File

@@ -41,8 +41,8 @@
#include <QApplication>
#include <QDebug>
#include "fs_utils.h"
#include "preferences.h"
#include "core/utils/fs.h"
#include "core/preferences.h"
class SearchCategories: public QObject, public QHash<QString, QString> {
Q_OBJECT
@@ -148,7 +148,7 @@ public slots:
QProcess nova;
nova.setEnvironment(QProcess::systemEnvironment());
QStringList params;
params << fsutils::toNativePath(fsutils::searchEngineLocation()+"/nova2.py");
params << Utils::Fs::toNativePath(Utils::Fs::searchEngineLocation()+"/nova2.py");
params << "--capabilities";
nova.start("python", params, QIODevice::ReadOnly);
nova.waitForStarted();