mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-03 22:22:33 -06:00
Compare commits
2 Commits
3de2a9f486
...
d02b01c733
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d02b01c733 | ||
|
|
10b879bdaf |
@@ -28,9 +28,11 @@
|
||||
|
||||
#include "searchdownloadhandler.h"
|
||||
|
||||
#include <QtLogging>
|
||||
#include <QProcess>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/path.h"
|
||||
#include "base/utils/foreignapps.h"
|
||||
#include "base/utils/fs.h"
|
||||
@@ -38,6 +40,8 @@
|
||||
|
||||
SearchDownloadHandler::SearchDownloadHandler(const QString &pluginName, const QString &url, SearchPluginManager *manager)
|
||||
: QObject(manager)
|
||||
, m_pluginName {pluginName}
|
||||
, m_url {url}
|
||||
, m_manager {manager}
|
||||
, m_downloadProcess {new QProcess(this)}
|
||||
{
|
||||
@@ -58,10 +62,17 @@ SearchDownloadHandler::SearchDownloadHandler(const QString &pluginName, const QS
|
||||
m_downloadProcess->start(Utils::ForeignApps::pythonInfo().executablePath.data(), params, QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
void SearchDownloadHandler::downloadProcessFinished(int exitcode)
|
||||
void SearchDownloadHandler::downloadProcessFinished(const int exitcode)
|
||||
{
|
||||
QString path;
|
||||
const auto errMsg = QString::fromUtf8(m_downloadProcess->readAllStandardError()).trimmed();
|
||||
if (!errMsg.isEmpty())
|
||||
{
|
||||
qWarning("%s", qUtf8Printable(errMsg));
|
||||
LogMsg(tr("Error occurred when downloading torrent via search engine. Engine: \"%1\". URL: \"%2\". Error: \"%3\".")
|
||||
.arg(m_pluginName, m_url, errMsg), Log::WARNING);
|
||||
}
|
||||
|
||||
QString path;
|
||||
if ((exitcode == 0) && (m_downloadProcess->exitStatus() == QProcess::NormalExit))
|
||||
{
|
||||
const QString line = QString::fromUtf8(m_downloadProcess->readAllStandardOutput()).trimmed();
|
||||
@@ -70,5 +81,5 @@ void SearchDownloadHandler::downloadProcessFinished(int exitcode)
|
||||
path = parts[0].toString();
|
||||
}
|
||||
|
||||
emit downloadFinished(path);
|
||||
emit downloadFinished(path, errMsg);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class QProcess;
|
||||
|
||||
@@ -44,11 +45,13 @@ class SearchDownloadHandler : public QObject
|
||||
SearchDownloadHandler(const QString &pluginName, const QString &url, SearchPluginManager *manager);
|
||||
|
||||
signals:
|
||||
void downloadFinished(const QString &path);
|
||||
void downloadFinished(const QString &path, const QString &errorMessage);
|
||||
|
||||
private:
|
||||
void downloadProcessFinished(int exitcode);
|
||||
|
||||
QString m_pluginName;
|
||||
QString m_url;
|
||||
SearchPluginManager *m_manager = nullptr;
|
||||
QProcess *m_downloadProcess = nullptr;
|
||||
};
|
||||
|
||||
@@ -31,12 +31,14 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <QtLogging>
|
||||
#include <QList>
|
||||
#include <QMetaObject>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/path.h"
|
||||
#include "base/utils/bytearray.h"
|
||||
#include "base/utils/foreignapps.h"
|
||||
@@ -59,6 +61,26 @@ namespace
|
||||
PL_PUB_DATE,
|
||||
NB_PLUGIN_COLUMNS
|
||||
};
|
||||
|
||||
QString toString(const QProcess::ProcessError error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case QProcess::FailedToStart:
|
||||
return SearchHandler::tr("Process failed to start");
|
||||
case QProcess::Crashed:
|
||||
return SearchHandler::tr("Process crashed");
|
||||
case QProcess::Timedout:
|
||||
return SearchHandler::tr("Process timed out");
|
||||
case QProcess::WriteError:
|
||||
return SearchHandler::tr("Process write error");
|
||||
case QProcess::ReadError:
|
||||
return SearchHandler::tr("Process read error");
|
||||
case QProcess::UnknownError:
|
||||
return SearchHandler::tr("Process unknown error");
|
||||
}
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
SearchHandler::SearchHandler(const QString &pattern, const QString &category, const QStringList &usedPlugins, SearchPluginManager *manager)
|
||||
@@ -86,7 +108,16 @@ SearchHandler::SearchHandler(const QString &pattern, const QString &category, co
|
||||
};
|
||||
m_searchProcess->setArguments(params + m_pattern.split(u' '));
|
||||
|
||||
connect(m_searchProcess, &QProcess::errorOccurred, this, &SearchHandler::processFailed);
|
||||
connect(m_searchProcess, &QProcess::errorOccurred, this, [this](const QProcess::ProcessError error)
|
||||
{
|
||||
if (!m_searchCancelled)
|
||||
{
|
||||
const auto errMsg = toString(error);
|
||||
LogMsg(tr("Search process failed. Search query: \"%1\". Category: \"%2\". Engines: \"%3\". Error: \"%4\".")
|
||||
.arg(m_pattern, m_category, m_usedPlugins.join(u", "), errMsg), Log::WARNING);
|
||||
emit searchFailed(errMsg);
|
||||
}
|
||||
});
|
||||
connect(m_searchProcess, &QProcess::readyReadStandardOutput, this, &SearchHandler::readSearchOutput);
|
||||
connect(m_searchProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished)
|
||||
, this, &SearchHandler::processFinished);
|
||||
@@ -127,12 +158,20 @@ void SearchHandler::processFinished(const int exitcode)
|
||||
{
|
||||
m_searchTimeout->stop();
|
||||
|
||||
const auto errMsg = QString::fromUtf8(m_searchProcess->readAllStandardError()).trimmed();
|
||||
if (!errMsg.isEmpty())
|
||||
{
|
||||
qWarning("%s", qUtf8Printable(errMsg));
|
||||
LogMsg(tr("Error occurred in search engine. Search query: \"%1\". Category: \"%2\". Engines: \"%3\". Error: \"%4\".")
|
||||
.arg(m_pattern, m_category, m_usedPlugins.join(u", "), errMsg), Log::WARNING);
|
||||
}
|
||||
|
||||
if (m_searchCancelled)
|
||||
emit searchFinished(true);
|
||||
else if ((m_searchProcess->exitStatus() == QProcess::NormalExit) && (exitcode == 0))
|
||||
emit searchFinished(false);
|
||||
else
|
||||
emit searchFailed();
|
||||
emit searchFailed(errMsg);
|
||||
}
|
||||
|
||||
// search QProcess return output as soon as it gets new
|
||||
@@ -161,12 +200,6 @@ void SearchHandler::readSearchOutput()
|
||||
}
|
||||
}
|
||||
|
||||
void SearchHandler::processFailed()
|
||||
{
|
||||
if (!m_searchCancelled)
|
||||
emit searchFailed();
|
||||
}
|
||||
|
||||
// Parse one line of search results list
|
||||
// Line is in the following form:
|
||||
// file url | file name | file size | nb seeds | nb leechers | Search engine url
|
||||
|
||||
@@ -74,12 +74,11 @@ public:
|
||||
|
||||
signals:
|
||||
void searchFinished(bool cancelled = false);
|
||||
void searchFailed();
|
||||
void searchFailed(const QString &errorMessage);
|
||||
void newSearchResults(const QList<SearchResult> &results);
|
||||
|
||||
private:
|
||||
void readSearchOutput();
|
||||
void processFailed();
|
||||
void processFinished(int exitcode);
|
||||
bool parseSearchResult(QByteArrayView line, SearchResult &searchResult);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QtLogging>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QDomDocument>
|
||||
@@ -559,6 +560,13 @@ void SearchPluginManager::update()
|
||||
nova.start(Utils::ForeignApps::pythonInfo().executablePath.data(), params, QIODevice::ReadOnly);
|
||||
nova.waitForFinished();
|
||||
|
||||
if (const auto errMsg = QString::fromUtf8(nova.readAllStandardError()).trimmed()
|
||||
; !errMsg.isEmpty())
|
||||
{
|
||||
qWarning("%s", qUtf8Printable(errMsg));
|
||||
LogMsg(tr("Error occurred when fetching search engine capabilities. Error: \"%1\".").arg(errMsg), Log::WARNING);
|
||||
}
|
||||
|
||||
const auto capabilities = QString::fromUtf8(nova.readAllStandardOutput());
|
||||
QDomDocument xmlDoc;
|
||||
if (!xmlDoc.setContent(capabilities))
|
||||
|
||||
@@ -64,10 +64,12 @@ namespace
|
||||
return QApplication::palette().color(QPalette::Disabled, QPalette::WindowText);
|
||||
}
|
||||
|
||||
QString statusText(SearchJobWidget::Status st)
|
||||
QString statusText(const SearchJobWidget::Status st)
|
||||
{
|
||||
switch (st)
|
||||
{
|
||||
case SearchJobWidget::Status::Ready:
|
||||
break;
|
||||
case SearchJobWidget::Status::Ongoing:
|
||||
return SearchJobWidget::tr("Searching...");
|
||||
case SearchJobWidget::Status::Finished:
|
||||
@@ -78,9 +80,8 @@ namespace
|
||||
return SearchJobWidget::tr("An error occurred during search...");
|
||||
case SearchJobWidget::Status::NoResults:
|
||||
return SearchJobWidget::tr("Search returned no results");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +403,7 @@ void SearchJobWidget::copyField(const int column) const
|
||||
QApplication::clipboard()->setText(list.join(u'\n'));
|
||||
}
|
||||
|
||||
void SearchJobWidget::setStatus(Status value)
|
||||
void SearchJobWidget::setStatus(const Status value)
|
||||
{
|
||||
if (m_status == value)
|
||||
return;
|
||||
@@ -426,9 +427,12 @@ void SearchJobWidget::downloadTorrent(const QModelIndex &rowIndex, const AddTorr
|
||||
else
|
||||
{
|
||||
SearchDownloadHandler *downloadHandler = SearchPluginManager::instance()->downloadTorrent(engineName, torrentUrl);
|
||||
connect(downloadHandler, &SearchDownloadHandler::downloadFinished
|
||||
, this, [this, option](const QString &source) { addTorrentToSession(source, option); });
|
||||
connect(downloadHandler, &SearchDownloadHandler::downloadFinished, downloadHandler, &SearchDownloadHandler::deleteLater);
|
||||
connect(downloadHandler, &SearchDownloadHandler::downloadFinished, this
|
||||
, [this, downloadHandler, option](const QString &source, [[maybe_unused]] const QString &errorMessage)
|
||||
{
|
||||
addTorrentToSession(source, option);
|
||||
downloadHandler->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
setRowVisited(rowIndex.row());
|
||||
@@ -631,7 +635,7 @@ void SearchJobWidget::searchFinished(bool cancelled)
|
||||
setStatus(Status::Finished);
|
||||
}
|
||||
|
||||
void SearchJobWidget::searchFailed()
|
||||
void SearchJobWidget::searchFailed([[maybe_unused]] const QString &errorMessage)
|
||||
{
|
||||
setStatus(Status::Error);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ private:
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
void onItemDoubleClicked(const QModelIndex &index);
|
||||
void searchFinished(bool cancelled);
|
||||
void searchFailed();
|
||||
void searchFailed(const QString &errorMessage);
|
||||
void appendSearchResults(const QList<SearchResult> &results);
|
||||
void updateResultsCount();
|
||||
void setStatus(Status value);
|
||||
|
||||
@@ -114,8 +114,8 @@ void SearchController::startAction()
|
||||
|
||||
const auto id = generateSearchId();
|
||||
const std::shared_ptr<SearchHandler> searchHandler {SearchPluginManager::instance()->startSearch(pattern, category, pluginsToUse)};
|
||||
QObject::connect(searchHandler.get(), &SearchHandler::searchFinished, this, [id, this]() { m_activeSearches.remove(id); });
|
||||
QObject::connect(searchHandler.get(), &SearchHandler::searchFailed, this, [id, this]() { m_activeSearches.remove(id); });
|
||||
connect(searchHandler.get(), &SearchHandler::searchFinished, this, [this, id] { m_activeSearches.remove(id); });
|
||||
connect(searchHandler.get(), &SearchHandler::searchFailed, this, [this, id]([[maybe_unused]] const QString &errorMessage) { m_activeSearches.remove(id); });
|
||||
|
||||
m_searchHandlers.insert(id, searchHandler);
|
||||
|
||||
@@ -235,8 +235,8 @@ void SearchController::downloadTorrentAction()
|
||||
else
|
||||
{
|
||||
SearchDownloadHandler *downloadHandler = SearchPluginManager::instance()->downloadTorrent(pluginName, torrentUrl);
|
||||
connect(downloadHandler, &SearchDownloadHandler::downloadFinished
|
||||
, this, [this, downloadHandler](const QString &source)
|
||||
connect(downloadHandler, &SearchDownloadHandler::downloadFinished, this
|
||||
, [this, downloadHandler](const QString &source, [[maybe_unused]] const QString &errorMessage)
|
||||
{
|
||||
app()->addTorrentManager()->addTorrent(source);
|
||||
downloadHandler->deleteLater();
|
||||
|
||||
@@ -503,7 +503,7 @@
|
||||
const iframeElement = document.createElement("iframe");
|
||||
iframeElement.id = "rssDescription";
|
||||
iframeElement.sandbox = "allow-same-origin"; // allowed to get parent css
|
||||
iframeElement.srcdoc = `<html ${rootColor}><head><meta charset="utf-8"><link rel="stylesheet" type="text/css" href="css/style.css?v=${CACHEID}"></head><body>${articleDescription}</body></html>`;
|
||||
iframeElement.srcdoc = `<html ${rootColor}><head><meta charset="utf-8"><meta name="referrer" content="same-origin"><link rel="stylesheet" type="text/css" href="css/style.css?v=${CACHEID}"></head><body>${articleDescription}</body></html>`;
|
||||
|
||||
detailsView.append(iframeElement);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user