mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-11 07:18:08 +00:00
Merge pull request #14676 from Chocobo1/watcher
Revise folder monitoring functions in WebUI
This commit is contained in:
commit
0b3d088782
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
#if defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
@ -42,9 +44,11 @@
|
|||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const int WATCH_INTERVAL = 10000; // 10 sec
|
const std::chrono::duration WATCH_INTERVAL = 10s;
|
||||||
const int MAX_PARTIAL_RETRIES = 5;
|
const int MAX_PARTIAL_RETRIES = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QtContainerFwd>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
@ -39,9 +38,10 @@
|
|||||||
* Subclassing QFileSystemWatcher in order to support Network File
|
* Subclassing QFileSystemWatcher in order to support Network File
|
||||||
* System watching (NFS, CIFS) on Linux and Mac OS.
|
* System watching (NFS, CIFS) on Linux and Mac OS.
|
||||||
*/
|
*/
|
||||||
class FileSystemWatcher : public QFileSystemWatcher
|
class FileSystemWatcher final : public QFileSystemWatcher
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(FileSystemWatcher)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileSystemWatcher(QObject *parent = nullptr);
|
explicit FileSystemWatcher(QObject *parent = nullptr);
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void torrentsAdded(const QStringList &pathList);
|
void torrentsAdded(const QStringList &pathList);
|
||||||
|
|
||||||
protected slots:
|
private slots:
|
||||||
void scanLocalFolder(const QString &path);
|
void scanLocalFolder(const QString &path);
|
||||||
void processPartialTorrents();
|
void processPartialTorrents();
|
||||||
void scanNetworkFolders();
|
void scanNetworkFolders();
|
||||||
|
@ -394,15 +394,14 @@ void AppController::setPreferencesAction()
|
|||||||
if (hasKey("scan_dirs"))
|
if (hasKey("scan_dirs"))
|
||||||
{
|
{
|
||||||
const QVariantHash nativeDirs = it.value().toHash();
|
const QVariantHash nativeDirs = it.value().toHash();
|
||||||
QVariantHash oldScanDirs = pref->getScanDirs();
|
const QVariantHash oldScanDirs = pref->getScanDirs();
|
||||||
QVariantHash scanDirs;
|
QVariantHash scanDirs;
|
||||||
ScanFoldersModel *model = ScanFoldersModel::instance();
|
ScanFoldersModel *model = ScanFoldersModel::instance();
|
||||||
|
|
||||||
for (auto i = nativeDirs.cbegin(); i != nativeDirs.cend(); ++i)
|
for (auto i = nativeDirs.cbegin(); i != nativeDirs.cend(); ++i)
|
||||||
{
|
{
|
||||||
QString folder = Utils::Fs::toUniformPath(i.key());
|
int downloadType = 0;
|
||||||
int downloadType;
|
|
||||||
QString downloadPath;
|
QString downloadPath;
|
||||||
ScanFoldersModel::PathStatus ec;
|
|
||||||
if (i.value().type() == QVariant::String)
|
if (i.value().type() == QVariant::String)
|
||||||
{
|
{
|
||||||
downloadType = ScanFoldersModel::CUSTOM_LOCATION;
|
downloadType = ScanFoldersModel::CUSTOM_LOCATION;
|
||||||
@ -411,23 +410,17 @@ void AppController::setPreferencesAction()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
downloadType = i.value().toInt();
|
downloadType = i.value().toInt();
|
||||||
downloadPath = (downloadType == ScanFoldersModel::DEFAULT_LOCATION) ? "Default folder" : "Watch folder";
|
downloadPath = (downloadType == ScanFoldersModel::DEFAULT_LOCATION)
|
||||||
|
? QLatin1String("Default folder")
|
||||||
|
: QLatin1String("Watch folder");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oldScanDirs.contains(folder))
|
const QString folder = Utils::Fs::toUniformPath(i.key());
|
||||||
ec = model->addPath(folder, static_cast<ScanFoldersModel::PathType>(downloadType), downloadPath);
|
const ScanFoldersModel::PathStatus ec = !oldScanDirs.contains(folder)
|
||||||
else
|
? model->addPath(folder, static_cast<ScanFoldersModel::PathType>(downloadType), downloadPath)
|
||||||
ec = model->updatePath(folder, static_cast<ScanFoldersModel::PathType>(downloadType), downloadPath);
|
: model->updatePath(folder, static_cast<ScanFoldersModel::PathType>(downloadType), downloadPath);
|
||||||
|
|
||||||
if (ec == ScanFoldersModel::Ok)
|
if (ec == ScanFoldersModel::Ok)
|
||||||
{
|
scanDirs.insert(folder, ((downloadType == ScanFoldersModel::CUSTOM_LOCATION) ? QVariant(downloadPath) : QVariant(downloadType)));
|
||||||
scanDirs.insert(folder, (downloadType == ScanFoldersModel::CUSTOM_LOCATION) ? QVariant(downloadPath) : QVariant(downloadType));
|
|
||||||
qDebug("New watched folder: %s to %s", qUtf8Printable(folder), qUtf8Printable(downloadPath));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qDebug("Watched folder %s failed with error %d", qUtf8Printable(folder), ec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update deleted folders
|
// Update deleted folders
|
||||||
@ -435,11 +428,9 @@ void AppController::setPreferencesAction()
|
|||||||
{
|
{
|
||||||
const QString &folder = i.key();
|
const QString &folder = i.key();
|
||||||
if (!scanDirs.contains(folder))
|
if (!scanDirs.contains(folder))
|
||||||
{
|
|
||||||
model->removePath(folder);
|
model->removePath(folder);
|
||||||
qDebug("Removed watched folder %s", qUtf8Printable(folder));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pref->setScanDirs(scanDirs);
|
pref->setScanDirs(scanDirs);
|
||||||
}
|
}
|
||||||
// Email notification upon download completion
|
// Email notification upon download completion
|
||||||
|
@ -127,22 +127,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td style="padding-top:4px;"><input type="text" id="new_watch_folder_txt" autocorrect="off" autocapitalize="none" /></td>
|
|
||||||
<td style="padding-top:4px;">
|
|
||||||
<div class="select-watched-folder-editable">
|
|
||||||
<select id="new_watch_folder_select" onchange="qBittorrent.Preferences.changeWatchFolderSelect(this)">
|
|
||||||
<option value="watch_folder">QBT_TR(Monitored folder)QBT_TR[CONTEXT=ScanFoldersModel]</option>
|
|
||||||
<option selected value="default_folder">QBT_TR(Default save location)QBT_TR[CONTEXT=ScanFoldersModel]</option>
|
|
||||||
<option value="other">QBT_TR(Other...)QBT_TR[CONTEXT=HttpServer]</option>
|
|
||||||
</select>
|
|
||||||
<input id="new_watch_folder_other_txt" type="text" value="QBT_TR(Monitored folder)QBT_TR[CONTEXT=ScanFoldersModel]" hidden />
|
|
||||||
<img src="icons/list-add.svg" alt="Add" style="padding-left:170px;width:16px;cursor:pointer;" onclick="qBittorrent.Preferences.addWatchFolder();" />
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@ -1283,37 +1267,17 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Downloads tab
|
// Downloads tab
|
||||||
const WatchedFoldersTable = new HtmlTable($("watched_folders_tab"));
|
const watchedFoldersTable = new HtmlTable($("watched_folders_tab"));
|
||||||
|
|
||||||
const updateTempDirEnabled = function() {
|
const updateTempDirEnabled = function() {
|
||||||
const isTempDirEnabled = $('temppath_checkbox').getProperty('checked');
|
const isTempDirEnabled = $('temppath_checkbox').getProperty('checked');
|
||||||
$('temppath_text').setProperty('disabled', !isTempDirEnabled);
|
$('temppath_text').setProperty('disabled', !isTempDirEnabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
const addWatchFolder = function() {
|
const changeWatchFolderSelect = (item) => {
|
||||||
const new_folder = $('new_watch_folder_txt').getProperty('value').trim();
|
if (item.value === "other") {
|
||||||
if (new_folder.length <= 0) return;
|
|
||||||
|
|
||||||
const new_other = $('new_watch_folder_other_txt').getProperty('value').trim();
|
|
||||||
if (new_other.length <= 0) return;
|
|
||||||
|
|
||||||
const new_select = $('new_watch_folder_select').getProperty('value').trim();
|
|
||||||
|
|
||||||
const i = $('watched_folders_tab').getChildren('tbody')[0].getChildren('tr').length;
|
|
||||||
pushWatchFolder(i, new_folder, new_select, new_other);
|
|
||||||
|
|
||||||
// Clear fields
|
|
||||||
$('new_watch_folder_txt').setProperty('value', '');
|
|
||||||
const elt = $('new_watch_folder_select');
|
|
||||||
elt.setProperty('value', 'watch_folder');
|
|
||||||
const text = elt.options[elt.selectedIndex].innerHTML;
|
|
||||||
$('new_watch_folder_other_txt').setProperty('value', text);
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeWatchFolderSelect = function(item) {
|
|
||||||
if (item.value == "other") {
|
|
||||||
item.nextElementSibling.hidden = false;
|
item.nextElementSibling.hidden = false;
|
||||||
item.nextElementSibling.value = 'QBT_TR(Type folder here)QBT_TR[CONTEXT=HttpServer]';
|
item.nextElementSibling.value = 'QBT_TR(Type folder here)QBT_TR[CONTEXT=ScanFoldersModel]';
|
||||||
item.nextElementSibling.select();
|
item.nextElementSibling.select();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1323,40 +1287,47 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const pushWatchFolder = function(pos, folder, sel, other) {
|
const addWatchFolder = (folder = "", sel = "default_folder", other = "") => {
|
||||||
|
const pos = $('watched_folders_tab').getChildren('tbody')[0].getChildren('tr').length;
|
||||||
const myinput = "<input id='text_watch_" + pos + "' type='text' value='" + folder + "'>";
|
const myinput = "<input id='text_watch_" + pos + "' type='text' value='" + folder + "'>";
|
||||||
const disableInput = (sel != "other");
|
const disableInput = (sel !== "other");
|
||||||
const mycb = "<div class='select-watched-folder-editable'>"
|
const mycb = "<div class='select-watched-folder-editable'>"
|
||||||
+ "<select id ='cb_watch_" + pos + "' onchange='qBittorrent.Preferences.changeWatchFolderSelect(this)'>"
|
+ "<select id ='cb_watch_" + pos + "' onchange='qBittorrent.Preferences.changeWatchFolderSelect(this)'>"
|
||||||
+ "<option value='watch_folder'>QBT_TR(Monitored folder)QBT_TR[CONTEXT=ScanFoldersModel]</option>"
|
+ "<option value='watch_folder'>QBT_TR(Monitored folder)QBT_TR[CONTEXT=ScanFoldersModel]</option>"
|
||||||
+ "<option value='default_folder'>QBT_TR(Default save location)QBT_TR[CONTEXT=ScanFoldersModel]</option>"
|
+ "<option value='default_folder'>QBT_TR(Default save location)QBT_TR[CONTEXT=ScanFoldersModel]</option>"
|
||||||
+ "<option value='other'>QBT_TR(Other...)QBT_TR[CONTEXT=HttpServer]</option>"
|
+ "<option value='other'>QBT_TR(Other...)QBT_TR[CONTEXT=ScanFoldersModel]</option>"
|
||||||
+ "</select>"
|
+ "</select>"
|
||||||
+ "<input id='cb_watch_txt_" + pos + "' type='text' " + (disableInput ? "hidden " : "") + "/></div>";
|
+ "<input id='cb_watch_txt_" + pos + "' type='text' " + (disableInput ? "hidden " : "") + "/>"
|
||||||
|
+ "<img src='icons/list-add.svg' id='addFolderImg_" + pos + "' alt='Add' style='padding-left:170px;width:16px;cursor:pointer;' onclick='qBittorrent.Preferences.addWatchFolder();' />"
|
||||||
|
+ "</div>";
|
||||||
|
|
||||||
WatchedFoldersTable.push([myinput, mycb]);
|
watchedFoldersTable.push([myinput, mycb]);
|
||||||
$('cb_watch_' + pos).setProperty('value', sel);
|
$('cb_watch_' + pos).setProperty('value', sel);
|
||||||
if (disableInput) {
|
if (disableInput) {
|
||||||
const elt = $('cb_watch_' + pos);
|
const elt = $('cb_watch_' + pos);
|
||||||
other = elt.options[elt.selectedIndex].innerHTML;
|
other = elt.options[elt.selectedIndex].innerHTML;
|
||||||
}
|
}
|
||||||
$('cb_watch_txt_' + pos).setProperty('value', other);
|
$('cb_watch_txt_' + pos).setProperty('value', other);
|
||||||
|
|
||||||
|
// hide previous img
|
||||||
|
if (pos > 0)
|
||||||
|
$('addFolderImg_' + (pos - 1)).style.display = "none";
|
||||||
};
|
};
|
||||||
|
|
||||||
const getWatchedFolders = function() {
|
const getWatchedFolders = () => {
|
||||||
const nb_folders = $("watched_folders_tab").getChildren("tbody")[0].getChildren("tr").length;
|
const nb_folders = $("watched_folders_tab").getChildren("tbody")[0].getChildren("tr").length;
|
||||||
const folders = new Hash();
|
const folders = new Hash();
|
||||||
for (let i = 0; i < nb_folders; ++i) {
|
for (let i = 0; i < nb_folders; ++i) {
|
||||||
const fpath = $('text_watch_' + i).getProperty('value').trim();
|
const fpath = $('text_watch_' + i).getProperty('value').trim();
|
||||||
if (fpath.length > 0) {
|
if (fpath.length > 0) {
|
||||||
let other;
|
|
||||||
const sel = $('cb_watch_' + i).getProperty('value').trim();
|
const sel = $('cb_watch_' + i).getProperty('value').trim();
|
||||||
if (sel == "other") {
|
|
||||||
|
let other;
|
||||||
|
if (sel === "other")
|
||||||
other = $('cb_watch_txt_' + i).getProperty('value').trim();
|
other = $('cb_watch_txt_' + i).getProperty('value').trim();
|
||||||
}
|
else
|
||||||
else {
|
other = (sel === "watch_folder") ? 0 : 1;
|
||||||
other = (sel == "watch_folder") ? 0 : 1;
|
|
||||||
}
|
|
||||||
folders.set(fpath, other);
|
folders.set(fpath, other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1663,19 +1634,19 @@
|
|||||||
updateExportDirFinEnabled();
|
updateExportDirFinEnabled();
|
||||||
|
|
||||||
// Automatically add torrents from
|
// Automatically add torrents from
|
||||||
let i = 0;
|
for (const [folder, folderType] of Object.entries(pref.scan_dirs)) {
|
||||||
for (const folder in pref.scan_dirs) {
|
let sel = "";
|
||||||
let sel;
|
|
||||||
let other = "";
|
let other = "";
|
||||||
if (typeof pref.scan_dirs[folder] == "string") {
|
if (typeof folderType === "number") {
|
||||||
other = pref.scan_dirs[folder];
|
sel = (folderType === 0) ? "watch_folder" : "default_folder";
|
||||||
sel = "other";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sel = (pref.scan_dirs[folder] == 0) ? "watch_folder" : "default_folder";
|
sel = "other";
|
||||||
|
other = folderType;
|
||||||
}
|
}
|
||||||
pushWatchFolder(i++, folder, sel, other);
|
addWatchFolder(folder, sel, other);
|
||||||
}
|
}
|
||||||
|
addWatchFolder();
|
||||||
|
|
||||||
// Email notification upon download completion
|
// Email notification upon download completion
|
||||||
$('mail_notification_checkbox').setProperty('checked', pref.mail_notification_enabled);
|
$('mail_notification_checkbox').setProperty('checked', pref.mail_notification_enabled);
|
||||||
|
Loading…
Reference in New Issue
Block a user