mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
commit
1820a03f1d
15 changed files with 1957 additions and 1679 deletions
File diff suppressed because it is too large
Load diff
|
@ -42,7 +42,8 @@ QT_END_NAMESPACE
|
||||||
class QTorrentState
|
class QTorrentState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
Unknown = -1,
|
Unknown = -1,
|
||||||
|
|
||||||
Error,
|
Error,
|
||||||
|
@ -71,93 +72,96 @@ private:
|
||||||
|
|
||||||
// A wrapper for torrent_handle in libtorrent
|
// A wrapper for torrent_handle in libtorrent
|
||||||
// to interact well with Qt types
|
// to interact well with Qt types
|
||||||
class QTorrentHandle : public libtorrent::torrent_handle {
|
class QTorrentHandle: public libtorrent::torrent_handle
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constructors
|
// Constructors
|
||||||
//
|
//
|
||||||
|
|
||||||
QTorrentHandle() {}
|
QTorrentHandle() {}
|
||||||
explicit QTorrentHandle(const libtorrent::torrent_handle& h);
|
explicit QTorrentHandle(const libtorrent::torrent_handle& h);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Getters
|
// Getters
|
||||||
//
|
//
|
||||||
QString hash() const;
|
QString hash() const;
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QString current_tracker() const;
|
QString current_tracker() const;
|
||||||
bool is_paused() const;
|
bool is_paused() const;
|
||||||
bool has_filtered_pieces() const;
|
bool has_filtered_pieces() const;
|
||||||
libtorrent::size_type total_size() const;
|
libtorrent::size_type total_size() const;
|
||||||
libtorrent::size_type piece_length() const;
|
libtorrent::size_type piece_length() const;
|
||||||
int num_pieces() const;
|
int num_pieces() const;
|
||||||
QString save_path() const;
|
QString save_path() const;
|
||||||
QString save_path_parsed() const;
|
QString save_path_parsed() const;
|
||||||
QStringList url_seeds() const;
|
QStringList url_seeds() const;
|
||||||
libtorrent::size_type actual_size() const;
|
libtorrent::size_type actual_size() const;
|
||||||
int num_files() const;
|
int num_files() const;
|
||||||
int queue_position() const;
|
int queue_position() const;
|
||||||
bool is_queued() const;
|
bool is_queued() const;
|
||||||
QString filename_at(unsigned int index) const;
|
QString filename_at(unsigned int index) const;
|
||||||
libtorrent::size_type filesize_at(unsigned int index) const;
|
libtorrent::size_type filesize_at(unsigned int index) const;
|
||||||
QString filepath_at(unsigned int index) const;
|
QString filepath_at(unsigned int index) const;
|
||||||
QString orig_filepath_at(unsigned int index) const;
|
QString orig_filepath_at(unsigned int index) const;
|
||||||
libtorrent::torrent_status::state_t state() const;
|
libtorrent::torrent_status::state_t state() const;
|
||||||
QString creator() const;
|
QString creator() const;
|
||||||
QString comment() const;
|
QString comment() const;
|
||||||
QStringList absolute_files_path() const;
|
QStringList absolute_files_path() const;
|
||||||
QStringList absolute_files_path_uneeded() const;
|
QStringList absolute_files_path_uneeded() const;
|
||||||
bool has_missing_files() const;
|
bool has_missing_files() const;
|
||||||
bool is_seed() const;
|
bool is_seed() const;
|
||||||
bool is_checking() const;
|
bool is_checking() const;
|
||||||
bool is_sequential_download() const;
|
bool is_sequential_download() const;
|
||||||
QString creation_date() const;
|
QString creation_date() const;
|
||||||
qlonglong creation_date_unix() const;
|
qlonglong creation_date_unix() const;
|
||||||
bool priv() const;
|
bool priv() const;
|
||||||
bool first_last_piece_first() const;
|
bool first_last_piece_first() const;
|
||||||
QString root_path() const;
|
QString root_path() const;
|
||||||
QString firstFileSavePath() const;
|
QString firstFileSavePath() const;
|
||||||
bool has_error() const;
|
bool has_error() const;
|
||||||
QString error() const;
|
QString error() const;
|
||||||
void downloading_pieces(libtorrent::bitfield& bf) const;
|
void downloading_pieces(libtorrent::bitfield& bf) const;
|
||||||
bool has_metadata() const;
|
bool has_metadata() const;
|
||||||
void file_progress(std::vector<libtorrent::size_type>& fp) const;
|
void file_progress(std::vector<libtorrent::size_type>& fp) const;
|
||||||
QTorrentState torrentState() const;
|
QTorrentState torrentState() const;
|
||||||
qulonglong eta() const;
|
qulonglong eta() const;
|
||||||
|
void toggleSequentialDownload();
|
||||||
|
void toggleFirstLastPiecePrio();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setters
|
// Setters
|
||||||
//
|
//
|
||||||
void pause() const;
|
void pause() const;
|
||||||
void resume() const;
|
void resume() const;
|
||||||
void remove_url_seed(const QString& seed) const;
|
void remove_url_seed(const QString& seed) const;
|
||||||
void add_url_seed(const QString& seed) const;
|
void add_url_seed(const QString& seed) const;
|
||||||
void set_tracker_login(const QString& username, const QString& password) const;
|
void set_tracker_login(const QString& username, const QString& password) const;
|
||||||
void move_storage(const QString& path) const;
|
void move_storage(const QString& path) const;
|
||||||
void prioritize_first_last_piece(bool b) const;
|
void prioritize_first_last_piece(bool b) const;
|
||||||
void rename_file(int index, const QString& name) const;
|
void rename_file(int index, const QString& name) const;
|
||||||
bool save_torrent_file(const QString& path) const;
|
bool save_torrent_file(const QString& path) const;
|
||||||
void prioritize_files(const std::vector<int>& files) const;
|
void prioritize_files(const std::vector<int>& files) const;
|
||||||
void file_priority(int index, int priority) const;
|
void file_priority(int index, int priority) const;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Operators
|
// Operators
|
||||||
//
|
//
|
||||||
bool operator ==(const QTorrentHandle& new_h) const;
|
bool operator ==(const QTorrentHandle& new_h) const;
|
||||||
|
|
||||||
static bool is_paused(const libtorrent::torrent_status &status);
|
static bool is_paused(const libtorrent::torrent_status &status);
|
||||||
static int queue_position(const libtorrent::torrent_status &status);
|
static int queue_position(const libtorrent::torrent_status &status);
|
||||||
static bool is_queued(const libtorrent::torrent_status &status);
|
static bool is_queued(const libtorrent::torrent_status &status);
|
||||||
static bool is_seed(const libtorrent::torrent_status &status);
|
static bool is_seed(const libtorrent::torrent_status &status);
|
||||||
static bool is_checking(const libtorrent::torrent_status &status);
|
static bool is_checking(const libtorrent::torrent_status &status);
|
||||||
static bool has_error(const libtorrent::torrent_status &status);
|
static bool has_error(const libtorrent::torrent_status &status);
|
||||||
static float progress(const libtorrent::torrent_status &status);
|
static float progress(const libtorrent::torrent_status &status);
|
||||||
static QString filepath_at(const libtorrent::torrent_info &info, unsigned int index);
|
static QString filepath_at(const libtorrent::torrent_info &info, unsigned int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prioritize_first_last_piece(int file_index, bool b) const;
|
void prioritize_first_last_piece(int file_index, bool b) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,77 +47,78 @@ class QSortFilterProxyModel;
|
||||||
class QStandardItemModel;
|
class QStandardItemModel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class TransferListWidget: public QTreeView {
|
class TransferListWidget: public QTreeView
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession* BTSession);
|
TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession* BTSession);
|
||||||
~TransferListWidget();
|
~TransferListWidget();
|
||||||
TorrentModel* getSourceModel() const;
|
TorrentModel* getSourceModel() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setSelectionLabel(QString label);
|
void setSelectionLabel(QString label);
|
||||||
void setRefreshInterval(int t);
|
void setRefreshInterval(int t);
|
||||||
void setSelectedTorrentsLocation();
|
void setSelectedTorrentsLocation();
|
||||||
void startSelectedTorrents();
|
void startSelectedTorrents();
|
||||||
void startVisibleTorrents();
|
void startVisibleTorrents();
|
||||||
void pauseSelectedTorrents();
|
void pauseSelectedTorrents();
|
||||||
void pauseVisibleTorrents();
|
void pauseVisibleTorrents();
|
||||||
void deleteSelectedTorrents();
|
void deleteSelectedTorrents();
|
||||||
void deleteVisibleTorrents();
|
void deleteVisibleTorrents();
|
||||||
void increasePrioSelectedTorrents();
|
void increasePrioSelectedTorrents();
|
||||||
void decreasePrioSelectedTorrents();
|
void decreasePrioSelectedTorrents();
|
||||||
void topPrioSelectedTorrents();
|
void topPrioSelectedTorrents();
|
||||||
void bottomPrioSelectedTorrents();
|
void bottomPrioSelectedTorrents();
|
||||||
void copySelectedMagnetURIs() const;
|
void copySelectedMagnetURIs() const;
|
||||||
void openSelectedTorrentsFolder() const;
|
void openSelectedTorrentsFolder() const;
|
||||||
void recheckSelectedTorrents();
|
void recheckSelectedTorrents();
|
||||||
void setDlLimitSelectedTorrents();
|
void setDlLimitSelectedTorrents();
|
||||||
void setUpLimitSelectedTorrents();
|
void setUpLimitSelectedTorrents();
|
||||||
void setMaxRatioSelectedTorrents();
|
void setMaxRatioSelectedTorrents();
|
||||||
void previewSelectedTorrents();
|
void previewSelectedTorrents();
|
||||||
void hidePriorityColumn(bool hide);
|
void hidePriorityColumn(bool hide);
|
||||||
void displayDLHoSMenu(const QPoint&);
|
void displayDLHoSMenu(const QPoint&);
|
||||||
void applyNameFilter(const QString& name);
|
void applyNameFilter(const QString& name);
|
||||||
void applyStatusFilter(int f);
|
void applyStatusFilter(int f);
|
||||||
void applyLabelFilterAll();
|
void applyLabelFilterAll();
|
||||||
void applyLabelFilter(QString label);
|
void applyLabelFilter(QString label);
|
||||||
void previewFile(QString filePath);
|
void previewFile(QString filePath);
|
||||||
void removeLabelFromRows(QString label);
|
void removeLabelFromRows(QString label);
|
||||||
void renameSelectedTorrent();
|
void renameSelectedTorrent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int getRowFromHash(QString hash) const;
|
int getRowFromHash(QString hash) const;
|
||||||
QString getHashFromRow(int row) const;
|
QString getHashFromRow(int row) const;
|
||||||
QModelIndex mapToSource(const QModelIndex &index) const;
|
QModelIndex mapToSource(const QModelIndex &index) const;
|
||||||
QModelIndex mapFromSource(const QModelIndex &index) const;
|
QModelIndex mapFromSource(const QModelIndex &index) const;
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
bool loadSettings();
|
bool loadSettings();
|
||||||
QStringList getSelectedTorrentsHashes() const;
|
QStringList getSelectedTorrentsHashes() const;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void torrentDoubleClicked(const QModelIndex& index);
|
void torrentDoubleClicked(const QModelIndex& index);
|
||||||
void displayListMenu(const QPoint&);
|
void displayListMenu(const QPoint&);
|
||||||
void currentChanged(const QModelIndex& current, const QModelIndex&);
|
void currentChanged(const QModelIndex& current, const QModelIndex&);
|
||||||
void toggleSelectedTorrentsSuperSeeding() const;
|
void toggleSelectedTorrentsSuperSeeding() const;
|
||||||
void toggleSelectedTorrentsSequentialDownload() const;
|
void toggleSelectedTorrentsSequentialDownload() const;
|
||||||
void toggleSelectedFirstLastPiecePrio() const;
|
void toggleSelectedFirstLastPiecePrio() const;
|
||||||
void askNewLabelForSelection();
|
void askNewLabelForSelection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool openUrl(const QString& _path) const;
|
bool openUrl(const QString& _path) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentTorrentChanged(const QTorrentHandle &h);
|
void currentTorrentChanged(const QTorrentHandle &h);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TransferListDelegate *listDelegate;
|
TransferListDelegate *listDelegate;
|
||||||
TorrentModel *listModel;
|
TorrentModel *listModel;
|
||||||
TransferListSortModel *nameFilterModel;
|
TransferListSortModel *nameFilterModel;
|
||||||
QBtSession* BTSession;
|
QBtSession* BTSession;
|
||||||
MainWindow *main_window;
|
MainWindow *main_window;
|
||||||
QShortcut *editHotkey;
|
QShortcut *editHotkey;
|
||||||
QShortcut *deleteHotkey;
|
QShortcut *deleteHotkey;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRANSFERLISTWIDGET_H
|
#endif // TRANSFERLISTWIDGET_H
|
||||||
|
|
|
@ -36,145 +36,134 @@
|
||||||
#include "abstractrequesthandler.h"
|
#include "abstractrequesthandler.h"
|
||||||
|
|
||||||
AbstractRequestHandler::AbstractRequestHandler(const HttpRequest &request, const HttpEnvironment &env, WebApplication *app)
|
AbstractRequestHandler::AbstractRequestHandler(const HttpRequest &request, const HttpEnvironment &env, WebApplication *app)
|
||||||
: app_(app), session_(0), request_(request), env_(env)
|
: app_(app), session_(0), request_(request), env_(env)
|
||||||
{
|
{
|
||||||
sessionInitialize();
|
sessionInitialize();
|
||||||
if (!sessionActive() && !isAuthNeeded())
|
if (!sessionActive() && !isAuthNeeded())
|
||||||
sessionStart();
|
sessionStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpResponse AbstractRequestHandler::run()
|
HttpResponse AbstractRequestHandler::run()
|
||||||
{
|
{
|
||||||
response_ = HttpResponse();
|
response_ = HttpResponse();
|
||||||
|
|
||||||
if (isBanned())
|
if (isBanned()) {
|
||||||
{
|
status(403, "Forbidden");
|
||||||
status(403, "Forbidden");
|
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts."), CONTENT_TYPE_TXT);
|
||||||
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts."), CONTENT_TYPE_TXT);
|
}
|
||||||
}
|
else {
|
||||||
else
|
processRequest();
|
||||||
{
|
}
|
||||||
processRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
return response_;
|
return response_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractRequestHandler::isAuthNeeded()
|
bool AbstractRequestHandler::isAuthNeeded()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(
|
(
|
||||||
env_.clientAddress != QHostAddress::LocalHost &&
|
env_.clientAddress != QHostAddress::LocalHost &&
|
||||||
env_.clientAddress != QHostAddress::LocalHostIPv6
|
env_.clientAddress != QHostAddress::LocalHostIPv6
|
||||||
) || Preferences::instance()->isWebUiLocalAuthEnabled();
|
) || Preferences::instance()->isWebUiLocalAuthEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::status(uint code, const QString& text)
|
void AbstractRequestHandler::status(uint code, const QString& text)
|
||||||
{
|
{
|
||||||
response_.status = HttpResponseStatus(code, text);
|
response_.status = HttpResponseStatus(code, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::header(const QString& name, const QString& value)
|
void AbstractRequestHandler::header(const QString& name, const QString& value)
|
||||||
{
|
{
|
||||||
response_.headers[name] = value;
|
response_.headers[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::print(const QString& text, const QString& type)
|
void AbstractRequestHandler::print(const QString& text, const QString& type)
|
||||||
{
|
{
|
||||||
print_impl(text.toUtf8(), type);
|
print_impl(text.toUtf8(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::print(const QByteArray& data, const QString& type)
|
void AbstractRequestHandler::print(const QByteArray& data, const QString& type)
|
||||||
{
|
{
|
||||||
print_impl(data, type);
|
print_impl(data, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::print_impl(const QByteArray& data, const QString& type)
|
void AbstractRequestHandler::print_impl(const QByteArray& data, const QString& type)
|
||||||
{
|
{
|
||||||
if (!response_.headers.contains(HEADER_CONTENT_TYPE))
|
if (!response_.headers.contains(HEADER_CONTENT_TYPE))
|
||||||
response_.headers[HEADER_CONTENT_TYPE] = type;
|
response_.headers[HEADER_CONTENT_TYPE] = type;
|
||||||
|
|
||||||
if (type.indexOf("image") > -1)
|
response_.content += data;
|
||||||
response_.headers[HEADER_CACHE_CONTROL] = "max-age=3000000";
|
|
||||||
|
|
||||||
response_.content += data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::printFile(const QString& path)
|
void AbstractRequestHandler::printFile(const QString& path)
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
QString type;
|
QString type;
|
||||||
|
|
||||||
if (!app_->readFile(path, data, type))
|
if (!app_->readFile(path, data, type)) {
|
||||||
{
|
status(404, "Not Found");
|
||||||
status(404, "Not Found");
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
print(data, type);
|
print(data, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::sessionInitialize()
|
void AbstractRequestHandler::sessionInitialize()
|
||||||
{
|
{
|
||||||
app_->sessionInitialize(this);
|
app_->sessionInitialize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::sessionStart()
|
void AbstractRequestHandler::sessionStart()
|
||||||
{
|
{
|
||||||
if (app_->sessionStart(this))
|
if (app_->sessionStart(this)) {
|
||||||
{
|
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
||||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
cookie.setPath("/");
|
||||||
cookie.setPath("/");
|
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
||||||
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::sessionEnd()
|
void AbstractRequestHandler::sessionEnd()
|
||||||
{
|
{
|
||||||
if (sessionActive())
|
if (sessionActive()) {
|
||||||
{
|
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
||||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
cookie.setPath("/");
|
||||||
cookie.setPath("/");
|
cookie.setExpirationDate(QDateTime::currentDateTime());
|
||||||
cookie.setExpirationDate(QDateTime::currentDateTime());
|
|
||||||
|
|
||||||
if (app_->sessionEnd(this))
|
if (app_->sessionEnd(this))
|
||||||
{
|
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
||||||
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractRequestHandler::isBanned() const
|
bool AbstractRequestHandler::isBanned() const
|
||||||
{
|
{
|
||||||
return app_->isBanned(this);
|
return app_->isBanned(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AbstractRequestHandler::failedAttempts() const
|
int AbstractRequestHandler::failedAttempts() const
|
||||||
{
|
{
|
||||||
return app_->failedAttempts(this);
|
return app_->failedAttempts(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::resetFailedAttempts()
|
void AbstractRequestHandler::resetFailedAttempts()
|
||||||
{
|
{
|
||||||
app_->resetFailedAttempts(this);
|
app_->resetFailedAttempts(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractRequestHandler::increaseFailedAttempts()
|
void AbstractRequestHandler::increaseFailedAttempts()
|
||||||
{
|
{
|
||||||
app_->increaseFailedAttempts(this);
|
app_->increaseFailedAttempts(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AbstractRequestHandler::saveTmpFile(const QByteArray &data)
|
QString AbstractRequestHandler::saveTmpFile(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QTemporaryFile tmpfile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent"));
|
QTemporaryFile tmpfile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent"));
|
||||||
tmpfile.setAutoRemove(false);
|
tmpfile.setAutoRemove(false);
|
||||||
if (tmpfile.open())
|
if (tmpfile.open()) {
|
||||||
{
|
tmpfile.write(data);
|
||||||
tmpfile.write(data);
|
tmpfile.close();
|
||||||
tmpfile.close();
|
return tmpfile.fileName();
|
||||||
return tmpfile.fileName();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
qWarning() << "I/O Error: Could not create temporary file";
|
qWarning() << "I/O Error: Could not create temporary file";
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ using namespace libtorrent;
|
||||||
static QElapsedTimer cacheTimer; \
|
static QElapsedTimer cacheTimer; \
|
||||||
static bool initialized = false; \
|
static bool initialized = false; \
|
||||||
if (initialized && !cacheTimer.hasExpired(DUR)) \
|
if (initialized && !cacheTimer.hasExpired(DUR)) \
|
||||||
return json::toJson(VAR); \
|
return json::toJson(VAR); \
|
||||||
initialized = true; \
|
initialized = true; \
|
||||||
cacheTimer.start(); \
|
cacheTimer.start(); \
|
||||||
VAR = VARTYPE()
|
VAR = VARTYPE()
|
||||||
|
@ -65,7 +65,7 @@ using namespace libtorrent;
|
||||||
static QString prev_hash; \
|
static QString prev_hash; \
|
||||||
static QElapsedTimer cacheTimer; \
|
static QElapsedTimer cacheTimer; \
|
||||||
if (prev_hash == HASH && !cacheTimer.hasExpired(DUR)) \
|
if (prev_hash == HASH && !cacheTimer.hasExpired(DUR)) \
|
||||||
return json::toJson(VAR); \
|
return json::toJson(VAR); \
|
||||||
prev_hash = HASH; \
|
prev_hash = HASH; \
|
||||||
cacheTimer.start(); \
|
cacheTimer.start(); \
|
||||||
VAR = VARTYPE()
|
VAR = VARTYPE()
|
||||||
|
@ -98,6 +98,8 @@ static const char KEY_TORRENT_NUM_INCOMPLETE[] = "num_incomplete";
|
||||||
static const char KEY_TORRENT_RATIO[] = "ratio";
|
static const char KEY_TORRENT_RATIO[] = "ratio";
|
||||||
static const char KEY_TORRENT_ETA[] = "eta";
|
static const char KEY_TORRENT_ETA[] = "eta";
|
||||||
static const char KEY_TORRENT_STATE[] = "state";
|
static const char KEY_TORRENT_STATE[] = "state";
|
||||||
|
static const char KEY_TORRENT_SEQUENTIAL_DOWNLOAD[] = "seq_dl";
|
||||||
|
static const char KEY_TORRENT_FIRST_LAST_PIECE_PRIO[] = "f_l_piece_prio";
|
||||||
|
|
||||||
// Tracker keys
|
// Tracker keys
|
||||||
static const char KEY_TRACKER_URL[] = "url";
|
static const char KEY_TRACKER_URL[] = "url";
|
||||||
|
@ -157,26 +159,26 @@ public:
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case QVariant::Int:
|
case QVariant::Int:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toInt() > torrent2.toMap().value(key_).toInt()
|
return greaterThan_ ? torrent1.toMap().value(key_).toInt() > torrent2.toMap().value(key_).toInt()
|
||||||
: torrent1.toMap().value(key_).toInt() < torrent2.toMap().value(key_).toInt();
|
: torrent1.toMap().value(key_).toInt() < torrent2.toMap().value(key_).toInt();
|
||||||
case QVariant::LongLong:
|
case QVariant::LongLong:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toLongLong() > torrent2.toMap().value(key_).toLongLong()
|
return greaterThan_ ? torrent1.toMap().value(key_).toLongLong() > torrent2.toMap().value(key_).toLongLong()
|
||||||
: torrent1.toMap().value(key_).toLongLong() < torrent2.toMap().value(key_).toLongLong();
|
: torrent1.toMap().value(key_).toLongLong() < torrent2.toMap().value(key_).toLongLong();
|
||||||
case QVariant::ULongLong:
|
case QVariant::ULongLong:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toULongLong() > torrent2.toMap().value(key_).toULongLong()
|
return greaterThan_ ? torrent1.toMap().value(key_).toULongLong() > torrent2.toMap().value(key_).toULongLong()
|
||||||
: torrent1.toMap().value(key_).toULongLong() < torrent2.toMap().value(key_).toULongLong();
|
: torrent1.toMap().value(key_).toULongLong() < torrent2.toMap().value(key_).toULongLong();
|
||||||
case QMetaType::Float:
|
case QMetaType::Float:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toFloat() > torrent2.toMap().value(key_).toFloat()
|
return greaterThan_ ? torrent1.toMap().value(key_).toFloat() > torrent2.toMap().value(key_).toFloat()
|
||||||
: torrent1.toMap().value(key_).toFloat() < torrent2.toMap().value(key_).toFloat();
|
: torrent1.toMap().value(key_).toFloat() < torrent2.toMap().value(key_).toFloat();
|
||||||
case QVariant::Double:
|
case QVariant::Double:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toDouble() > torrent2.toMap().value(key_).toDouble()
|
return greaterThan_ ? torrent1.toMap().value(key_).toDouble() > torrent2.toMap().value(key_).toDouble()
|
||||||
: torrent1.toMap().value(key_).toDouble() < torrent2.toMap().value(key_).toDouble();
|
: torrent1.toMap().value(key_).toDouble() < torrent2.toMap().value(key_).toDouble();
|
||||||
default:
|
default:
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_).toString() > torrent2.toMap().value(key_).toString()
|
return greaterThan_ ? torrent1.toMap().value(key_).toString() > torrent2.toMap().value(key_).toString()
|
||||||
: torrent1.toMap().value(key_).toString() < torrent2.toMap().value(key_).toString();
|
: torrent1.toMap().value(key_).toString() < torrent2.toMap().value(key_).toString();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return greaterThan_ ? torrent1.toMap().value(key_) > torrent2.toMap().value(key_)
|
return greaterThan_ ? torrent1.toMap().value(key_) > torrent2.toMap().value(key_)
|
||||||
: torrent1.toMap().value(key_) < torrent2.toMap().value(key_);
|
: torrent1.toMap().value(key_) < torrent2.toMap().value(key_);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +213,12 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
||||||
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio;
|
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio;
|
||||||
ret[KEY_TORRENT_STATE] = h.torrentState().toString();
|
ret[KEY_TORRENT_STATE] = h.torrentState().toString();
|
||||||
ret[KEY_TORRENT_ETA] = h.eta();
|
ret[KEY_TORRENT_ETA] = h.eta();
|
||||||
|
if (h.has_metadata()) {
|
||||||
|
if (status.sequential_download)
|
||||||
|
ret[KEY_TORRENT_SEQUENTIAL_DOWNLOAD] = true;
|
||||||
|
if (h.first_last_piece_first())
|
||||||
|
ret[KEY_TORRENT_FIRST_LAST_PIECE_PRIO] = true;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +244,7 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
||||||
* - "state": Torrent state
|
* - "state": Torrent state
|
||||||
*/
|
*/
|
||||||
QByteArray btjson::getTorrents(QString filter, QString label,
|
QByteArray btjson::getTorrents(QString filter, QString label,
|
||||||
QString sortedColumn, bool reverse, int limit, int offset)
|
QString sortedColumn, bool reverse, int limit, int offset)
|
||||||
{
|
{
|
||||||
QVariantList torrent_list;
|
QVariantList torrent_list;
|
||||||
|
|
||||||
|
@ -245,7 +253,7 @@ QByteArray btjson::getTorrents(QString filter, QString label,
|
||||||
std::vector<torrent_handle>::const_iterator end = torrents.end();
|
std::vector<torrent_handle>::const_iterator end = torrents.end();
|
||||||
|
|
||||||
QTorrentFilter torrentFilter(filter, label);
|
QTorrentFilter torrentFilter(filter, label);
|
||||||
for( ; it != end; ++it) {
|
for(; it != end; ++it) {
|
||||||
QTorrentHandle torrent = QTorrentHandle(*it);
|
QTorrentHandle torrent = QTorrentHandle(*it);
|
||||||
|
|
||||||
if (torrentFilter.apply(torrent))
|
if (torrentFilter.apply(torrent))
|
||||||
|
@ -294,8 +302,9 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
|
||||||
tracker_dict[KEY_TRACKER_URL] = tracker_url;
|
tracker_dict[KEY_TRACKER_URL] = tracker_url;
|
||||||
const TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
const TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||||
QString status;
|
QString status;
|
||||||
if (it->verified)
|
if (it->verified) {
|
||||||
status = tr("Working");
|
status = tr("Working");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (it->updating && it->fails == 0)
|
if (it->updating && it->fails == 0)
|
||||||
status = tr("Updating...");
|
status = tr("Updating...");
|
||||||
|
|
|
@ -62,6 +62,7 @@ const QString SCOPE_THEME = "theme";
|
||||||
const QString DEFAULT_ACTION = "index";
|
const QString DEFAULT_ACTION = "index";
|
||||||
const QString WEBUI_ACTION = "webui";
|
const QString WEBUI_ACTION = "webui";
|
||||||
const QString VERSION_INFO = "version";
|
const QString VERSION_INFO = "version";
|
||||||
|
const QString MAX_AGE_MONTH = "public, max-age=2592000";
|
||||||
|
|
||||||
#define ADD_ACTION(scope, action) actions[#scope][#action] = &RequestHandler::action_##scope##_##action
|
#define ADD_ACTION(scope, action) actions[#scope][#action] = &RequestHandler::action_##scope##_##action
|
||||||
|
|
||||||
|
@ -99,6 +100,8 @@ QMap<QString, QMap<QString, RequestHandler::Action> > RequestHandler::initialize
|
||||||
ADD_ACTION(command, getTorrentDlLimit);
|
ADD_ACTION(command, getTorrentDlLimit);
|
||||||
ADD_ACTION(command, setTorrentUpLimit);
|
ADD_ACTION(command, setTorrentUpLimit);
|
||||||
ADD_ACTION(command, setTorrentDlLimit);
|
ADD_ACTION(command, setTorrentDlLimit);
|
||||||
|
ADD_ACTION(command, toggleSequentialDownload);
|
||||||
|
ADD_ACTION(command, toggleFirstLastPiecePrio);
|
||||||
ADD_ACTION(command, delete);
|
ADD_ACTION(command, delete);
|
||||||
ADD_ACTION(command, deletePerm);
|
ADD_ACTION(command, deletePerm);
|
||||||
ADD_ACTION(command, increasePrio);
|
ADD_ACTION(command, increasePrio);
|
||||||
|
@ -178,12 +181,14 @@ void RequestHandler::action_public_theme()
|
||||||
qDebug() << Q_FUNC_INFO << "There icon:" << url;
|
qDebug() << Q_FUNC_INFO << "There icon:" << url;
|
||||||
|
|
||||||
printFile(url);
|
printFile(url);
|
||||||
|
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestHandler::action_public_images()
|
void RequestHandler::action_public_images()
|
||||||
{
|
{
|
||||||
const QString path = ":/Icons/" + args_.join("/");
|
const QString path = ":/Icons/" + args_.join("/");
|
||||||
printFile(path);
|
printFile(path);
|
||||||
|
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET params:
|
// GET params:
|
||||||
|
@ -423,6 +428,30 @@ void RequestHandler::action_command_setTorrentDlLimit()
|
||||||
h.set_download_limit(limit);
|
h.set_download_limit(limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequestHandler::action_command_toggleSequentialDownload()
|
||||||
|
{
|
||||||
|
QStringList hashes = request().posts["hashes"].split("|");
|
||||||
|
foreach (const QString &hash, hashes) {
|
||||||
|
try {
|
||||||
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
||||||
|
h.toggleSequentialDownload();
|
||||||
|
}
|
||||||
|
catch(invalid_handle&) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestHandler::action_command_toggleFirstLastPiecePrio()
|
||||||
|
{
|
||||||
|
QStringList hashes = request().posts["hashes"].split("|");
|
||||||
|
foreach (const QString &hash, hashes) {
|
||||||
|
try {
|
||||||
|
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash);
|
||||||
|
h.toggleFirstLastPiecePrio();
|
||||||
|
}
|
||||||
|
catch(invalid_handle&) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RequestHandler::action_command_delete()
|
void RequestHandler::action_command_delete()
|
||||||
{
|
{
|
||||||
QStringList hashes = request().posts["hashes"].split("|");
|
QStringList hashes = request().posts["hashes"].split("|");
|
||||||
|
|
|
@ -74,6 +74,8 @@ private:
|
||||||
void action_command_getTorrentDlLimit();
|
void action_command_getTorrentDlLimit();
|
||||||
void action_command_setTorrentUpLimit();
|
void action_command_setTorrentUpLimit();
|
||||||
void action_command_setTorrentDlLimit();
|
void action_command_setTorrentDlLimit();
|
||||||
|
void action_command_toggleSequentialDownload();
|
||||||
|
void action_command_toggleFirstLastPiecePrio();
|
||||||
void action_command_delete();
|
void action_command_delete();
|
||||||
void action_command_deletePerm();
|
void action_command_deletePerm();
|
||||||
void action_command_increasePrio();
|
void action_command_increasePrio();
|
||||||
|
|
|
@ -1,120 +1,125 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr">
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=10; IE=9; IE=8;" />
|
<meta http-equiv="X-UA-Compatible" content="IE=10; IE=9; IE=8;" />
|
||||||
<title>qBittorrent web User Interface</title>
|
<title>qBittorrent web User Interface</title>
|
||||||
<link rel="stylesheet" href="css/dynamicTable.css" type="text/css" />
|
<link rel="stylesheet" href="css/dynamicTable.css" type="text/css" />
|
||||||
<link rel="stylesheet" type="text/css" href="css/style.css" />
|
<link rel="stylesheet" type="text/css" href="css/style.css" />
|
||||||
<!--<link rel="stylesheet" type="text/css" href="css/Content.css" />-->
|
<!--<link rel="stylesheet" type="text/css" href="css/Content.css" />-->
|
||||||
<link rel="stylesheet" type="text/css" href="css/Core.css" />
|
<link rel="stylesheet" type="text/css" href="css/Core.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="css/Layout.css" />
|
<link rel="stylesheet" type="text/css" href="css/Layout.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="css/Window.css" />
|
<link rel="stylesheet" type="text/css" href="css/Window.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="css/Tabs.css" />
|
<link rel="stylesheet" type="text/css" href="css/Tabs.css" />
|
||||||
<script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script>
|
||||||
<script type="text/javascript" src="scripts/mootools-1.2-more.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/mootools-1.2-more.js" charset="utf-8"></script>
|
||||||
<!--[if IE]>
|
<!--[if IE]>
|
||||||
<script type="text/javascript" src="scripts/excanvas-compressed.js"></script>
|
<script type="text/javascript" src="scripts/excanvas-compressed.js"></script>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
<script type="text/javascript" src="scripts/mocha-yc.js"></script>
|
<script type="text/javascript" src="scripts/mocha-yc.js"></script>
|
||||||
<script type="text/javascript" src="scripts/mocha-init.js"></script>
|
<script type="text/javascript" src="scripts/mocha-init.js"></script>
|
||||||
<script type="text/javascript" src="scripts/misc.js"></script>
|
<script type="text/javascript" src="scripts/misc.js"></script>
|
||||||
<script type="text/javascript" src="scripts/progressbar.js"></script>
|
<script type="text/javascript" src="scripts/progressbar.js"></script>
|
||||||
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
|
||||||
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>
|
||||||
<script type="text/javascript" src="scripts/contextmenu.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/contextmenu.js" charset="utf-8"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="desktop">
|
<div id="desktop">
|
||||||
<div id="desktopHeader">
|
<div id="desktopHeader">
|
||||||
<!--<div id="desktopTitlebar">
|
<!--<div id="desktopTitlebar">
|
||||||
<h1 class="applicationTitle">qBittorrent Web User Interface <span class="version">version 2.0.0</span></h1>
|
<h1 class="applicationTitle">qBittorrent Web User Interface <span class="version">version 2.0.0</span></h1>
|
||||||
</div>-->
|
</div>-->
|
||||||
<div id="desktopNavbar">
|
<div id="desktopNavbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a class="returnFalse">_(File)</a>
|
<a class="returnFalse">_(File)</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id="uploadLink"><img class="MyMenuIcon" alt="_(&Add torrent file...)" src="theme/list-add" width="16" height="16" onload="fixPNG(this)"/>_(&Add torrent file...)</a></li>
|
<li><a id="uploadLink"><img class="MyMenuIcon" alt="_(&Add torrent file...)" src="theme/list-add" width="16" height="16" onload="fixPNG(this)"/>_(&Add torrent file...)</a></li>
|
||||||
<li><a id="downloadLink"><img class="MyMenuIcon" alt="_(Add &link to torrent...)" src="theme/insert-link" width="16" height="16" onload="fixPNG(this)"/>_(Add &link to torrent...)</a></li>
|
<li><a id="downloadLink"><img class="MyMenuIcon" alt="_(Add &link to torrent...)" src="theme/insert-link" width="16" height="16" onload="fixPNG(this)"/>_(Add &link to torrent...)</a></li>
|
||||||
<li class="divider"><a id="logoutLink"><img class="MyMenuIcon" alt="_(Logout)" src="theme/system-log-out" width="16" height="16" onload="fixPNG(this)"/>_(Logout)</a></li>
|
<li class="divider"><a id="logoutLink"><img class="MyMenuIcon" alt="_(Logout)" src="theme/system-log-out" width="16" height="16" onload="fixPNG(this)"/>_(Logout)</a></li>
|
||||||
<li><a id="shutdownLink"><img class="MyMenuIcon" alt="_(Exit qBittorrent)" src="theme/application-exit" width="16" height="16" onload="fixPNG(this)"/>_(Exit qBittorrent)</a></li>
|
<li><a id="shutdownLink"><img class="MyMenuIcon" alt="_(Exit qBittorrent)" src="theme/application-exit" width="16" height="16" onload="fixPNG(this)"/>_(Exit qBittorrent)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="returnFalse">_(Edit)</a>
|
<a class="returnFalse">_(Edit)</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id="resumeAllLink"><img class="MyMenuIcon" alt="_(R&esume All)" src="theme/media-playback-start" width="16" height="16" onload="fixPNG(this)"/>_(R&esume All)</a></li>
|
<li><a id="resumeAllLink"><img class="MyMenuIcon" alt="_(R&esume All)" src="theme/media-playback-start" width="16" height="16" onload="fixPNG(this)"/>_(R&esume All)</a></li>
|
||||||
<li><a id="pauseAllLink"><img class="MyMenuIcon" alt="_(P&ause All)" src="theme/media-playback-pause" width="16" height="16" onload="fixPNG(this)"/>_(P&ause All)</a></li>
|
<li><a id="pauseAllLink"><img class="MyMenuIcon" alt="_(P&ause All)" src="theme/media-playback-pause" width="16" height="16" onload="fixPNG(this)"/>_(P&ause All)</a></li>
|
||||||
<li class="divider"><a id="resumeLink"><img class="MyMenuIcon" alt="_(&Resume)" src="theme/media-playback-start" width="16" height="16" onload="fixPNG(this)"/>_(&Resume)</a></li>
|
<li class="divider"><a id="resumeLink"><img class="MyMenuIcon" alt="_(&Resume)" src="theme/media-playback-start" width="16" height="16" onload="fixPNG(this)"/>_(&Resume)</a></li>
|
||||||
<li><a id="pauseLink"><img class="MyMenuIcon" src="theme/media-playback-pause" alt="_(&Pause)" width="16" height="16" onload="fixPNG(this)"/>_(&Pause)</a></li>
|
<li><a id="pauseLink"><img class="MyMenuIcon" src="theme/media-playback-pause" alt="_(&Pause)" width="16" height="16" onload="fixPNG(this)"/>_(&Pause)</a></li>
|
||||||
<li><a id="recheckLink"><img class="MyMenuIcon" src="theme/document-edit-verify" alt="_(Force recheck)" width="16" height="16" onload="fixPNG(this)"/>_(Force recheck)</a></li>
|
<li><a id="recheckLink"><img class="MyMenuIcon" src="theme/document-edit-verify" alt="_(Force recheck)" width="16" height="16" onload="fixPNG(this)"/>_(Force recheck)</a></li>
|
||||||
<li class="divider"><a id="deleteLink"><img class="MyMenuIcon" src="theme/list-remove" alt="_(&Delete)" width="16" height="16" onload="fixPNG(this)"/>_(&Delete)</a></li>
|
<li class="divider"><a id="deleteLink"><img class="MyMenuIcon" src="theme/list-remove" alt="_(&Delete)" width="16" height="16" onload="fixPNG(this)"/>_(&Delete)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="returnFalse">_(&View)</a>
|
<a class="returnFalse">_(&View)</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id="speedInBrowserTitleBarLink"><img class="MyMenuIcon" src="theme/checked" alt="_(&Speed in title bar)" width="16" height="16" onload="fixPNG(this)"/>_(&Speed in title bar)</a></li>
|
<li><a id="speedInBrowserTitleBarLink"><img class="MyMenuIcon" src="theme/checked" alt="_(&Speed in title bar)" width="16" height="16" onload="fixPNG(this)"/>_(&Speed in title bar)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="returnFalse">_(&Tools)</a>
|
<a class="returnFalse">_(&Tools)</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id="preferencesLink"><img class="MyMenuIcon" src="theme/preferences-system" alt="_(&Options...)" width="16" height="16" onload="fixPNG(this)"/>_(&Options...)</a></li>
|
<li><a id="preferencesLink"><img class="MyMenuIcon" src="theme/preferences-system" alt="_(&Options...)" width="16" height="16" onload="fixPNG(this)"/>_(&Options...)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="returnFalse">_(&Help)</a>
|
<a class="returnFalse">_(&Help)</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id="bugLink" target="_blank" href="http://bugs.qbittorrent.org/"><img class="MyMenuIcon" src="theme/tools-report-bug" alt="_(Report a &bug)" width="16" height="16" onload="fixPNG(this)"/>_(Report a &bug)</a></li>
|
<li><a id="bugLink" target="_blank" href="http://bugs.qbittorrent.org/"><img class="MyMenuIcon" src="theme/tools-report-bug" alt="_(Report a &bug)" width="16" height="16" onload="fixPNG(this)"/>_(Report a &bug)</a></li>
|
||||||
<li><a id="siteLink" target="_blank" href="http://www.qbittorrent.org/"><img class="MyMenuIcon" src="images/skin/qbittorrent16.png" alt="_(Visit &Website)" width="16" height="16" onload="fixPNG(this)"/>_(Visit &Website)</a></li>
|
<li><a id="siteLink" target="_blank" href="http://www.qbittorrent.org/"><img class="MyMenuIcon" src="images/skin/qbittorrent16.png" alt="_(Visit &Website)" width="16" height="16" onload="fixPNG(this)"/>_(Visit &Website)</a></li>
|
||||||
<li><a id="docsLink" target="_blank" href="http://wiki.qbittorrent.org/"><img class="MyMenuIcon" src="theme/help-contents" alt="_(&Documentation)" width="16" height="16" onload="fixPNG(this)"/>_(&Documentation)</a></li>
|
<li><a id="docsLink" target="_blank" href="http://wiki.qbittorrent.org/"><img class="MyMenuIcon" src="theme/help-contents" alt="_(&Documentation)" width="16" height="16" onload="fixPNG(this)"/>_(&Documentation)</a></li>
|
||||||
<li><a id="aboutLink"><img class="MyMenuIcon" src="theme/help-about" alt="_(&About)" width="16" height="16" onload="fixPNG(this)"/>_(&About)</a></li>
|
<li><a id="aboutLink"><img class="MyMenuIcon" src="theme/help-about" alt="_(&About)" width="16" height="16" onload="fixPNG(this)"/>_(&About)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="mochaToolbar">
|
<div id="mochaToolbar">
|
||||||
|
|
||||||
<a id="uploadButton"><img class="mochaToolButton" title="_(&Add torrent file...)" src="theme/list-add" alt="_(&Add torrent file...)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="uploadButton"><img class="mochaToolButton" title="_(&Add torrent file...)" src="theme/list-add" alt="_(&Add torrent file...)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="downloadButton"><img class="mochaToolButton" title="_(Add &link to torrent...)" src="theme/insert-link" alt="_(Add &link to torrent...)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="downloadButton"><img class="mochaToolButton" title="_(Add &link to torrent...)" src="theme/insert-link" alt="_(Add &link to torrent...)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="deleteButton" class="divider"><img class="mochaToolButton" title="_(Delete)" src="theme/list-remove" alt="_(Delete)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="deleteButton" class="divider"><img class="mochaToolButton" title="_(Delete)" src="theme/list-remove" alt="_(Delete)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="resumeButton" class="divider"><img class="mochaToolButton" title="_(Resume)" src="theme/media-playback-start" alt="_(Resume)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="resumeButton" class="divider"><img class="mochaToolButton" title="_(Resume)" src="theme/media-playback-start" alt="_(Resume)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="pauseButton"><img class="mochaToolButton" title="_(Pause)" src="theme/media-playback-pause" alt="_(Pause)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="pauseButton"><img class="mochaToolButton" title="_(Pause)" src="theme/media-playback-pause" alt="_(Pause)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<span id="queueingButtons">
|
<span id="queueingButtons">
|
||||||
<a id="decreasePrioButton" class="divider"><img class="mochaToolButton" title="_(Decrease priority)" src="theme/go-down" alt="_(Decrease priority)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="bottomPrioButton" class="divider"><img class="mochaToolButton" title="_(Move to bottom)" src="theme/go-bottom" alt="_(Move to bottom)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="increasePrioButton"><img class="mochaToolButton" title="_(Increase priority)" src="theme/go-up" alt="_(Increase priority)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="decreasePrioButton"><img class="mochaToolButton" title="_(Decrease priority)" src="theme/go-down" alt="_(Decrease priority)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
</span>
|
<a id="increasePrioButton"><img class="mochaToolButton" title="_(Increase priority)" src="theme/go-up" alt="_(Increase priority)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<a id="preferencesButton" class="divider"><img class="mochaToolButton" title="_(Options)" src="theme/preferences-system" alt="_(Options)" width="24" height="24" onload="fixPNG(this)"/></a>
|
<a id="topPrioButton"><img class="mochaToolButton" title="_(Move to top)" src="theme/go-top" alt="_(Move to top)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
<a id="preferencesButton" class="divider"><img class="mochaToolButton" title="_(Options)" src="theme/preferences-system" alt="_(Options)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||||
<div id="pageWrapper">
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="pageWrapper">
|
||||||
<ul id="contextmenu">
|
</div>
|
||||||
<li><a href="#Start"><img src="theme/media-playback-start" alt="_(Resume)"/> _(Resume)</a></li>
|
</div>
|
||||||
<li><a href="#Pause"><img src="theme/media-playback-pause" alt="_(Pause)"/> _(Pause)</a></li>
|
<ul id="contextmenu">
|
||||||
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="_(Delete)"/> _(Delete)</a></li>
|
<li><a href="#Start"><img src="theme/media-playback-start" alt="_(Resume)"/> _(Resume)</a></li>
|
||||||
<li class="separator"><a href="#priority" class="arrow-right">_(Priority)</a>
|
<li><a href="#Pause"><img src="theme/media-playback-pause" alt="_(Pause)"/> _(Pause)</a></li>
|
||||||
<ul>
|
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="_(Delete)"/> _(Delete)</a></li>
|
||||||
<li><a href="#prioTop"><img src="theme/go-top" alt="_(Move to top)"/> _(Move to top)</a></li>
|
<li id="queueingMenuItems" class="separator">
|
||||||
<li><a href="#prioUp"><img src="theme/go-up" alt="_(Move up)"/> _(Move up)</a></li>
|
<a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> _(Priority)</a>
|
||||||
<li><a href="#prioDown"><img src="theme/go-down" alt="_(Move down)"/> _(Move down)</a></li>
|
<ul>
|
||||||
<li><a href="#prioBottom"><img src="theme/go-bottom" alt="_(Move to bottom)"/> _(Move to bottom)</a></li>
|
<li><a href="#prioTop"><img src="theme/go-top" alt="_(Move to top)"/> _(Move to top)</a></li>
|
||||||
</ul>
|
<li><a href="#prioUp"><img src="theme/go-up" alt="_(Move up)"/> _(Move up)</a></li>
|
||||||
</li>
|
<li><a href="#prioDown"><img src="theme/go-down" alt="_(Move down)"/> _(Move down)</a></li>
|
||||||
<li class="separator"><a href="#DownloadLimit"><img src="images/skin/download.png" alt="_(Limit download rate...)"/> _(Limit download rate...)</a></li>
|
<li><a href="#prioBottom"><img src="theme/go-bottom" alt="_(Move to bottom)"/> _(Move to bottom)</a></li>
|
||||||
<li><a href="#UploadLimit"><img src="images/skin/seeding.png" alt="_(Limit upload rate...)"/> _(Limit upload rate...)</a></li>
|
</ul>
|
||||||
<li class="separator"><a href="#ForceRecheck"><img src="theme/document-edit-verify" alt="_(Force recheck)"/> _(Force recheck)</a></li>
|
</li>
|
||||||
</ul>
|
<li class="separator"><a href="#DownloadLimit"><img src="images/skin/download.png" alt="_(Limit download rate...)"/> _(Limit download rate...)</a></li>
|
||||||
<div id="desktopFooterWrapper">
|
<li><a href="#UploadLimit"><img src="images/skin/seeding.png" alt="_(Limit upload rate...)"/> _(Limit upload rate...)</a></li>
|
||||||
<div id="desktopFooter">
|
<li class="separator"><a href="#SequentialDownload"><img src="theme/checked" alt="_(Download in sequential order)"/> _(Download in sequential order)</a></li>
|
||||||
<span id="error_div"></span>
|
<li><a href="#FirstLastPiecePrio"><img src="theme/checked" alt="_(Download first and last piece first)"/> _(Download first and last piece first)</a></li>
|
||||||
<table style="position: absolute; right: 5px;">
|
<li class="separator"><a href="#ForceRecheck"><img src="theme/document-edit-verify" alt="_(Force recheck)"/> _(Force recheck)</a></li>
|
||||||
<tr><td id="DlInfos" style="cursor:pointer;"></td><td style="width: 2px;margin:0;"><img src="images/skin/toolbox-divider.gif" alt="" style="height: 18px; padding-left: 10px; padding-right: 10px; margin-bottom: -2px;"/></td><td id="UpInfos" style="cursor:pointer;"></td></tr>
|
</ul>
|
||||||
</table>
|
<div id="desktopFooterWrapper">
|
||||||
</div>
|
<div id="desktopFooter">
|
||||||
</div>
|
<span id="error_div"></span>
|
||||||
|
<table style="position: absolute; right: 5px;">
|
||||||
|
<tr><td id="DlInfos" style="cursor:pointer;"></td><td style="width: 2px;margin:0;"><img src="images/skin/toolbox-divider.gif" alt="" style="height: 18px; padding-left: 10px; padding-right: 10px; margin-bottom: -2px;"/></td><td id="UpInfos" style="cursor:pointer;"></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
<ul class="filterList">
|
<ul class="filterList">
|
||||||
<li id="all_filter"><a href="#" onclick="setFilter('all');"><img src="images/skin/filterall.png"/>_(All)</a></li>
|
<li id="all_filter"><a href="#" onclick="setFilter('all');"><img src="images/skin/filterall.png"/>_(All)</a></li>
|
||||||
<li id="downloading_filter"><a href="#" onclick="setFilter('downloading');"><img src="images/skin/downloading.png"/>_(Downloading)</a></li>
|
<li id="downloading_filter"><a href="#" onclick="setFilter('downloading');"><img src="images/skin/downloading.png"/>_(Downloading)</a></li>
|
||||||
<li id="completed_filter"><a href="#" onclick="setFilter('completed');"><img src="images/skin/uploading.png"/>_(Completed)</a></li>
|
<li id="completed_filter"><a href="#" onclick="setFilter('completed');"><img src="images/skin/uploading.png"/>_(Completed)</a></li>
|
||||||
<li id="paused_filter"><a href="#" onclick="setFilter('paused');"><img src="images/skin/paused.png"/>_(Paused)</a></li>
|
<li id="paused_filter"><a href="#" onclick="setFilter('paused');"><img src="images/skin/paused.png"/>_(Paused)</a></li>
|
||||||
<li id="active_filter"><a href="#" onclick="setFilter('active');"><img src="images/skin/filteractive.png"/>_(Active)</a></li>
|
<li id="active_filter"><a href="#" onclick="setFilter('active');"><img src="images/skin/filteractive.png"/>_(Active)</a></li>
|
||||||
<li id="inactive_filter"><a href="#" onclick="setFilter('inactive');"><img src="images/skin/filterinactive.png"/>_(Inactive)</a></li>
|
<li id="inactive_filter"><a href="#" onclick="setFilter('inactive');"><img src="images/skin/filterinactive.png"/>_(Inactive)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
// Remember this via Cookie
|
|
||||||
var filter = Cookie.read('selected_filter');
|
|
||||||
if(!$defined(last_filter)) {
|
|
||||||
filter = 'all';
|
|
||||||
}
|
|
||||||
$(filter+'_filter').addClass('selectedFilter');
|
|
||||||
</script>
|
|
|
@ -24,6 +24,128 @@
|
||||||
|
|
||||||
myTable = new dynamicTable();
|
myTable = new dynamicTable();
|
||||||
|
|
||||||
|
var stateToImg = function (state) {
|
||||||
|
if (state == "pausedUP" || state == "pausedDL") {
|
||||||
|
state = "paused";
|
||||||
|
} else {
|
||||||
|
if (state == "queuedUP" || state == "queuedDL") {
|
||||||
|
state = "queued";
|
||||||
|
} else {
|
||||||
|
if (state == "checkingUP" || state == "checkingDL") {
|
||||||
|
state = "checking";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'images/skin/' + state + '.png';
|
||||||
|
};
|
||||||
|
|
||||||
|
filter = getLocalStorageItem('selected_filter', 'all');
|
||||||
|
|
||||||
|
var loadTorrentsInfoTimer;
|
||||||
|
var loadTorrentsInfo = function () {
|
||||||
|
var queueing_enabled = false;
|
||||||
|
var url = new URI('json/torrents');
|
||||||
|
url.setData('filter', filter);
|
||||||
|
url.setData('sort', myTable.table.sortedColumn);
|
||||||
|
url.setData('reverse', myTable.table.reverseSort);
|
||||||
|
var request = new Request.JSON({
|
||||||
|
url : url,
|
||||||
|
noCache : true,
|
||||||
|
method : 'get',
|
||||||
|
onFailure : function () {
|
||||||
|
$('error_div').set('html', '_(qBittorrent client is not reachable)');
|
||||||
|
loadTorrentsInfoTimer = loadTorrentsInfo.delay(2000);
|
||||||
|
},
|
||||||
|
onSuccess : function (events) {
|
||||||
|
$('error_div').set('html', '');
|
||||||
|
if (events) {
|
||||||
|
// Add new torrents or update them
|
||||||
|
torrent_hashes = myTable.getRowIds();
|
||||||
|
events_hashes = new Array();
|
||||||
|
pos = 0;
|
||||||
|
events.each(function (event) {
|
||||||
|
events_hashes[events_hashes.length] = event.hash;
|
||||||
|
var row = new Array();
|
||||||
|
var data = new Array();
|
||||||
|
row.length = 10;
|
||||||
|
row[0] = stateToImg(event.state);
|
||||||
|
row[1] = event.name;
|
||||||
|
row[2] = event.priority > -1 ? event.priority : null;
|
||||||
|
data[2] = event.priority;
|
||||||
|
row[3] = friendlyUnit(event.size, false);
|
||||||
|
data[3] = event.size;
|
||||||
|
row[4] = (event.progress * 100).round(1);
|
||||||
|
if (row[4] == 100.0 && event.progress != 1.0)
|
||||||
|
row[4] = 99.9;
|
||||||
|
data[4] = event.progress;
|
||||||
|
row[5] = event.num_seeds;
|
||||||
|
if (event.num_complete != -1)
|
||||||
|
row[5] += " (" + event.num_complete + ")";
|
||||||
|
data[5] = event.num_seeds;
|
||||||
|
row[6] = event.num_leechs;
|
||||||
|
if (event.num_incomplete != -1)
|
||||||
|
row[6] += " (" + event.num_incomplete + ")";
|
||||||
|
data[6] = event.num_leechs;
|
||||||
|
row[7] = friendlyUnit(event.dlspeed, true);
|
||||||
|
data[7] = event.dlspeed;
|
||||||
|
row[8] = friendlyUnit(event.upspeed, true);
|
||||||
|
data[8] = event.upspeed;
|
||||||
|
row[9] = friendlyDuration(event.eta);
|
||||||
|
data[9] = event.eta;
|
||||||
|
if (event.ratio == -1)
|
||||||
|
row[10] = "∞";
|
||||||
|
else
|
||||||
|
row[10] = (Math.floor(100 * event.ratio) / 100).toFixed(2); //Don't round up
|
||||||
|
data[10] = event.ratio;
|
||||||
|
if (row[2] != null)
|
||||||
|
queueing_enabled = true;
|
||||||
|
|
||||||
|
attrs = {};
|
||||||
|
attrs['downloaded'] = (event.progress == 1.0);
|
||||||
|
attrs['state'] = event.state;
|
||||||
|
attrs['seq_dl'] = (event.seq_dl == true);
|
||||||
|
attrs['f_l_piece_prio'] = (event.f_l_piece_prio == true);
|
||||||
|
|
||||||
|
if (!torrent_hashes.contains(event.hash)) {
|
||||||
|
// New unfinished torrent
|
||||||
|
torrent_hashes[torrent_hashes.length] = event.hash;
|
||||||
|
//alert("Inserting row");
|
||||||
|
myTable.insertRow(event.hash, row, data, attrs, pos);
|
||||||
|
} else {
|
||||||
|
// Update torrent data
|
||||||
|
myTable.updateRow(event.hash, row, data, attrs, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
});
|
||||||
|
// Remove deleted torrents
|
||||||
|
torrent_hashes.each(function (hash) {
|
||||||
|
if (!events_hashes.contains(hash)) {
|
||||||
|
myTable.removeRow(hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (queueing_enabled) {
|
||||||
|
$('queueingButtons').removeClass('invisible');
|
||||||
|
$('queueingMenuItems').removeClass('invisible');
|
||||||
|
myTable.showPriority();
|
||||||
|
} else {
|
||||||
|
$('queueingButtons').addClass('invisible');
|
||||||
|
$('queueingMenuItems').addClass('invisible');
|
||||||
|
myTable.hidePriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
myTable.altRow();
|
||||||
|
}
|
||||||
|
loadTorrentsInfoTimer = loadTorrentsInfo.delay(1500);
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateTransferList = function() {
|
||||||
|
clearTimeout(loadTorrentsInfoTimer);
|
||||||
|
loadTorrentsInfoTimer = loadTorrentsInfo();
|
||||||
|
}
|
||||||
|
|
||||||
window.addEvent('load', function () {
|
window.addEvent('load', function () {
|
||||||
|
|
||||||
var saveColumnSizes = function () {
|
var saveColumnSizes = function () {
|
||||||
|
@ -59,6 +181,23 @@ window.addEvent('load', function () {
|
||||||
resizeLimit : [100, 300]
|
resizeLimit : [100, 300]
|
||||||
});
|
});
|
||||||
MochaUI.Desktop.setDesktopSize();
|
MochaUI.Desktop.setDesktopSize();
|
||||||
|
|
||||||
|
setFilter = function (f) {
|
||||||
|
// Visually Select the right filter
|
||||||
|
$("all_filter").removeClass("selectedFilter");
|
||||||
|
$("downloading_filter").removeClass("selectedFilter");
|
||||||
|
$("completed_filter").removeClass("selectedFilter");
|
||||||
|
$("paused_filter").removeClass("selectedFilter");
|
||||||
|
$("active_filter").removeClass("selectedFilter");
|
||||||
|
$("inactive_filter").removeClass("selectedFilter");
|
||||||
|
$(f + "_filter").addClass("selectedFilter");
|
||||||
|
filter = f;
|
||||||
|
localStorage.setItem('selected_filter', f);
|
||||||
|
// Reload torrents
|
||||||
|
if (typeof myTable.table != 'undefined')
|
||||||
|
updateTransferList();
|
||||||
|
}
|
||||||
|
|
||||||
new MochaUI.Panel({
|
new MochaUI.Panel({
|
||||||
id : 'Filters',
|
id : 'Filters',
|
||||||
title : 'Panel',
|
title : 'Panel',
|
||||||
|
@ -71,6 +210,9 @@ window.addEvent('load', function () {
|
||||||
},
|
},
|
||||||
loadMethod : 'xhr',
|
loadMethod : 'xhr',
|
||||||
contentURL : 'filters.html',
|
contentURL : 'filters.html',
|
||||||
|
onContentLoaded : function () {
|
||||||
|
setFilter(filter);
|
||||||
|
},
|
||||||
column : 'filtersColumn',
|
column : 'filtersColumn',
|
||||||
height : 300
|
height : 300
|
||||||
});
|
});
|
||||||
|
@ -80,21 +222,6 @@ window.addEvent('load', function () {
|
||||||
if (!speedInTitle)
|
if (!speedInTitle)
|
||||||
$('speedInBrowserTitleBarLink').firstChild.style.opacity = '0';
|
$('speedInBrowserTitleBarLink').firstChild.style.opacity = '0';
|
||||||
|
|
||||||
var stateToImg = function (state) {
|
|
||||||
if (state == "pausedUP" || state == "pausedDL") {
|
|
||||||
state = "paused";
|
|
||||||
} else {
|
|
||||||
if (state == "queuedUP" || state == "queuedDL") {
|
|
||||||
state = "queued";
|
|
||||||
} else {
|
|
||||||
if (state == "checkingUP" || state == "checkingDL") {
|
|
||||||
state = "checking";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'images/skin/' + state + '.png';
|
|
||||||
};
|
|
||||||
|
|
||||||
var loadTransferInfoTimer;
|
var loadTransferInfoTimer;
|
||||||
var loadTransferInfo = function () {
|
var loadTransferInfo = function () {
|
||||||
var url = 'json/transferInfo';
|
var url = 'json/transferInfo';
|
||||||
|
@ -135,102 +262,6 @@ window.addEvent('load', function () {
|
||||||
$('DlInfos').addEvent('click', globalDownloadLimitFN);
|
$('DlInfos').addEvent('click', globalDownloadLimitFN);
|
||||||
$('UpInfos').addEvent('click', globalUploadLimitFN);
|
$('UpInfos').addEvent('click', globalUploadLimitFN);
|
||||||
|
|
||||||
var ajaxfnTimer;
|
|
||||||
var ajaxfn = function () {
|
|
||||||
var queueing_enabled = false;
|
|
||||||
var url = new URI('json/torrents');
|
|
||||||
url.setData('filter', filter);
|
|
||||||
url.setData('sort', myTable.table.sortedColumn);
|
|
||||||
url.setData('reverse', myTable.table.reverseSort);
|
|
||||||
var request = new Request.JSON({
|
|
||||||
url : url,
|
|
||||||
noCache : true,
|
|
||||||
method : 'get',
|
|
||||||
onFailure : function () {
|
|
||||||
$('error_div').set('html', '_(qBittorrent client is not reachable)');
|
|
||||||
ajaxfnTimer = ajaxfn.delay(2000);
|
|
||||||
},
|
|
||||||
onSuccess : function (events) {
|
|
||||||
$('error_div').set('html', '');
|
|
||||||
if (events) {
|
|
||||||
// Add new torrents or update them
|
|
||||||
torrent_hashes = myTable.getRowIds();
|
|
||||||
events_hashes = new Array();
|
|
||||||
pos = 0;
|
|
||||||
events.each(function (event) {
|
|
||||||
events_hashes[events_hashes.length] = event.hash;
|
|
||||||
var row = new Array();
|
|
||||||
var data = new Array();
|
|
||||||
row.length = 10;
|
|
||||||
row[0] = stateToImg(event.state);
|
|
||||||
row[1] = event.name;
|
|
||||||
row[2] = event.priority > -1 ? event.priority : null;
|
|
||||||
data[2] = event.priority;
|
|
||||||
row[3] = friendlyUnit(event.size, false);
|
|
||||||
data[3] = event.size;
|
|
||||||
row[4] = (event.progress * 100).round(1);
|
|
||||||
if (row[4] == 100.0 && event.progress != 1.0)
|
|
||||||
row[4] = 99.9;
|
|
||||||
data[4] = event.progress;
|
|
||||||
row[5] = event.num_seeds;
|
|
||||||
if (event.num_complete != -1)
|
|
||||||
row[5] += " (" + event.num_complete + ")";
|
|
||||||
data[5] = event.num_seeds;
|
|
||||||
row[6] = event.num_leechs;
|
|
||||||
if (event.num_incomplete != -1)
|
|
||||||
row[6] += " (" + event.num_incomplete + ")";
|
|
||||||
data[6] = event.num_leechs;
|
|
||||||
row[7] = friendlyUnit(event.dlspeed, true);
|
|
||||||
data[7] = event.dlspeed;
|
|
||||||
row[8] = friendlyUnit(event.upspeed, true);
|
|
||||||
data[8] = event.upspeed;
|
|
||||||
row[9] = friendlyDuration(event.eta);
|
|
||||||
data[9] = event.eta;
|
|
||||||
if (event.ratio == -1)
|
|
||||||
row[10] = "∞";
|
|
||||||
else
|
|
||||||
row[10] = (Math.floor(100 * event.ratio) / 100).toFixed(2); //Don't round up
|
|
||||||
data[10] = event.ratio;
|
|
||||||
if (row[2] != null)
|
|
||||||
queueing_enabled = true;
|
|
||||||
if (!torrent_hashes.contains(event.hash)) {
|
|
||||||
// New unfinished torrent
|
|
||||||
torrent_hashes[torrent_hashes.length] = event.hash;
|
|
||||||
//alert("Inserting row");
|
|
||||||
myTable.insertRow(event.hash, row, data, event.state, pos);
|
|
||||||
} else {
|
|
||||||
// Update torrent data
|
|
||||||
myTable.updateRow(event.hash, row, data, event.state, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos++;
|
|
||||||
});
|
|
||||||
// Remove deleted torrents
|
|
||||||
torrent_hashes.each(function (hash) {
|
|
||||||
if (!events_hashes.contains(hash)) {
|
|
||||||
myTable.removeRow(hash);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (queueing_enabled) {
|
|
||||||
$('queueingButtons').removeClass('invisible');
|
|
||||||
myTable.showPriority();
|
|
||||||
} else {
|
|
||||||
$('queueingButtons').addClass('invisible');
|
|
||||||
myTable.hidePriority();
|
|
||||||
}
|
|
||||||
|
|
||||||
myTable.altRow();
|
|
||||||
}
|
|
||||||
ajaxfnTimer = ajaxfn.delay(1500);
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
|
|
||||||
var updateTransferList = function() {
|
|
||||||
clearTimeout(ajaxfnTimer);
|
|
||||||
ajaxfnTimer = ajaxfn();
|
|
||||||
}
|
|
||||||
|
|
||||||
setSortedColumn = function (column) {
|
setSortedColumn = function (column) {
|
||||||
myTable.setSortedColumn(column);
|
myTable.setSortedColumn(column);
|
||||||
updateTransferList();
|
updateTransferList();
|
||||||
|
@ -288,22 +319,6 @@ window.addEvent('load', function () {
|
||||||
column : 'mainColumn',
|
column : 'mainColumn',
|
||||||
height : prop_h
|
height : prop_h
|
||||||
});
|
});
|
||||||
|
|
||||||
setFilter = function (f) {
|
|
||||||
// Visually Select the right filter
|
|
||||||
$("all_filter").removeClass("selectedFilter");
|
|
||||||
$("downloading_filter").removeClass("selectedFilter");
|
|
||||||
$("completed_filter").removeClass("selectedFilter");
|
|
||||||
$("paused_filter").removeClass("selectedFilter");
|
|
||||||
$("active_filter").removeClass("selectedFilter");
|
|
||||||
$("inactive_filter").removeClass("selectedFilter");
|
|
||||||
$(f + "_filter").addClass("selectedFilter");
|
|
||||||
filter = f;
|
|
||||||
localStorage.setItem('selected_filter', f);
|
|
||||||
// Reload torrents
|
|
||||||
updateTransferList();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function closeWindows() {
|
function closeWindows() {
|
||||||
|
|
|
@ -127,9 +127,89 @@ var ContextMenu = new Class({
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateMenuItems: function () {
|
||||||
|
all_are_seq_dl = true;
|
||||||
|
there_are_seq_dl = false;
|
||||||
|
all_are_f_l_piece_prio = true;
|
||||||
|
there_are_f_l_piece_prio = false;
|
||||||
|
all_are_downloaded = true;
|
||||||
|
all_are_paused = true;
|
||||||
|
there_are_paused = false;
|
||||||
|
|
||||||
|
var h = myTable.selectedIds();
|
||||||
|
h.each(function(item, index){
|
||||||
|
tr = myTable.rows.get(item);
|
||||||
|
|
||||||
|
if (tr.getAttribute('seq_dl') != 'true')
|
||||||
|
all_are_seq_dl = false;
|
||||||
|
else
|
||||||
|
there_are_seq_dl = true;
|
||||||
|
|
||||||
|
if (tr.getAttribute('f_l_piece_prio') != 'true')
|
||||||
|
all_are_f_l_piece_prio = false;
|
||||||
|
else
|
||||||
|
there_are_f_l_piece_prio = true;
|
||||||
|
|
||||||
|
if (tr.getAttribute('downloaded') != 'true')
|
||||||
|
all_are_downloaded = false;
|
||||||
|
|
||||||
|
state = tr.getAttribute('state');
|
||||||
|
if ((state != 'pausedUP') && (state != 'pausedDL'))
|
||||||
|
all_are_paused = false;
|
||||||
|
else
|
||||||
|
there_are_paused = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
show_seq_dl = true;
|
||||||
|
|
||||||
|
if (!all_are_seq_dl && there_are_seq_dl)
|
||||||
|
show_seq_dl = false;
|
||||||
|
|
||||||
|
show_f_l_piece_prio = true;
|
||||||
|
|
||||||
|
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
|
||||||
|
show_f_l_piece_prio = false;
|
||||||
|
|
||||||
|
if (all_are_downloaded) {
|
||||||
|
this.hideItem('SequentialDownload');
|
||||||
|
this.hideItem('FirstLastPiecePrio');
|
||||||
|
} else {
|
||||||
|
if (!show_seq_dl && show_f_l_piece_prio)
|
||||||
|
this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.addClass('separator');
|
||||||
|
else
|
||||||
|
this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.removeClass('separator');
|
||||||
|
|
||||||
|
if (show_seq_dl)
|
||||||
|
this.showItem('SequentialDownload');
|
||||||
|
else
|
||||||
|
this.hideItem('SequentialDownload');
|
||||||
|
|
||||||
|
if (show_f_l_piece_prio)
|
||||||
|
this.showItem('FirstLastPiecePrio');
|
||||||
|
else
|
||||||
|
this.hideItem('FirstLastPiecePrio');
|
||||||
|
|
||||||
|
this.setItemChecked('SequentialDownload', all_are_seq_dl);
|
||||||
|
this.setItemChecked('FirstLastPiecePrio', all_are_f_l_piece_prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_are_paused) {
|
||||||
|
this.showItem('Start');
|
||||||
|
this.hideItem('Pause');
|
||||||
|
} else {
|
||||||
|
if (there_are_paused) {
|
||||||
|
this.showItem('Start');
|
||||||
|
this.showItem('Pause');
|
||||||
|
} else {
|
||||||
|
this.hideItem('Start');
|
||||||
|
this.showItem('Pause');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
//show menu
|
//show menu
|
||||||
show: function(trigger) {
|
show: function(trigger) {
|
||||||
//this.menu.fade('in');
|
this.updateMenuItems();
|
||||||
this.fx.start(1);
|
this.fx.start(1);
|
||||||
this.fireEvent('show');
|
this.fireEvent('show');
|
||||||
this.shown = true;
|
this.shown = true;
|
||||||
|
@ -147,15 +227,21 @@ var ContextMenu = new Class({
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
//disable an item
|
setItemChecked: function(item, checked) {
|
||||||
disableItem: function(item) {
|
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
||||||
this.menu.getElements('a[href$=' + item + ']').addClass('disabled');
|
checked ? '1' : '0';
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
//enable an item
|
//hide an item
|
||||||
enableItem: function(item) {
|
hideItem: function(item) {
|
||||||
this.menu.getElements('a[href$=' + item + ']').removeClass('disabled');
|
this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
//show an item
|
||||||
|
showItem: function(item) {
|
||||||
|
this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible');
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -42,18 +42,20 @@ var dynamicTable = new Class({
|
||||||
this.priority_hidden = false;
|
this.priority_hidden = false;
|
||||||
this.progressIndex = progressIndex;
|
this.progressIndex = progressIndex;
|
||||||
this.context_menu = context_menu;
|
this.context_menu = context_menu;
|
||||||
this.table.sortedColumn = 'name'; // Default is NAME
|
this.table.sortedColumn = getLocalStorageItem('sorted_column', 'name');
|
||||||
this.table.reverseSort = false;
|
this.table.reverseSort = getLocalStorageItem('reverse_sort', 'false');;
|
||||||
},
|
},
|
||||||
|
|
||||||
setSortedColumn : function (column) {
|
setSortedColumn : function (column) {
|
||||||
if (column != this.table.sortedColumn) {
|
if (column != this.table.sortedColumn) {
|
||||||
this.table.sortedColumn = column;
|
this.table.sortedColumn = column;
|
||||||
this.table.reverseSort = false;
|
this.table.reverseSort = 'false';
|
||||||
} else {
|
} else {
|
||||||
// Toggle sort order
|
// Toggle sort order
|
||||||
this.table.reverseSort = !this.table.reverseSort;
|
this.table.reverseSort = this.table.reverseSort == 'true' ? 'false' : 'true';
|
||||||
}
|
}
|
||||||
|
localStorage.setItem('sorted_column', column);
|
||||||
|
localStorage.setItem('reverse_sort', this.table.reverseSort);
|
||||||
},
|
},
|
||||||
|
|
||||||
getCurrentTorrentHash : function () {
|
getCurrentTorrentHash : function () {
|
||||||
|
@ -100,11 +102,13 @@ var dynamicTable = new Class({
|
||||||
this.priority_hidden = false;
|
this.priority_hidden = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
insertRow : function (id, row, data, status, pos) {
|
insertRow : function (id, row, data, attrs, pos) {
|
||||||
if (this.rows.has(id)) {
|
if (this.rows.has(id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var tr = new Element('tr');
|
var tr = new Element('tr');
|
||||||
|
for (var a in attrs)
|
||||||
|
tr.set(a, attrs[a]);
|
||||||
tr.addClass("menu-target");
|
tr.addClass("menu-target");
|
||||||
this.rows.set(id, tr);
|
this.rows.set(id, tr);
|
||||||
for (var i = 0; i < row.length; i++) {
|
for (var i = 0; i < row.length; i++) {
|
||||||
|
@ -244,12 +248,14 @@ var dynamicTable = new Class({
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateRow : function (id, row, data, status, newpos) {
|
updateRow : function (id, row, data, attrs, newpos) {
|
||||||
if (!this.rows.has(id)) {
|
if (!this.rows.has(id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tr = this.rows.get(id);
|
var tr = this.rows.get(id);
|
||||||
|
for (var a in attrs)
|
||||||
|
tr.set(a, attrs[a]);
|
||||||
var tds = tr.getElements('td');
|
var tds = tr.getElements('td');
|
||||||
for (var i = 0; i < row.length; i++) {
|
for (var i = 0; i < row.length; i++) {
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* -----------------------------------------------------------------
|
/* -----------------------------------------------------------------
|
||||||
|
|
||||||
ATTACH MOCHA LINK EVENTS
|
ATTACH MOCHA LINK EVENTS
|
||||||
Notes: Here is where you define your windows and the events that open them.
|
Notes: Here is where you define your windows and the events that open them.
|
||||||
If you are not using links to run Mocha methods you can remove this function.
|
If you are not using links to run Mocha methods you can remove this function.
|
||||||
|
|
||||||
If you need to add link events to links within windows you are creating, do
|
If you need to add link events to links within windows you are creating, do
|
||||||
it in the onContentLoaded function of the new window.
|
it in the onContentLoaded function of the new window.
|
||||||
|
|
||||||
----------------------------------------------------------------- */
|
----------------------------------------------------------------- */
|
||||||
/* Define localStorage object for older browsers */
|
/* Define localStorage object for older browsers */
|
||||||
|
@ -22,6 +22,13 @@ if (typeof localStorage == 'undefined') {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLocalStorageItem(name, defaultVal) {
|
||||||
|
val = localStorage.getItem(name);
|
||||||
|
if (val === null || val === undefined)
|
||||||
|
val = defaultVal;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
initializeWindows = function() {
|
initializeWindows = function() {
|
||||||
|
|
||||||
function addClickEvent(el, fn) {
|
function addClickEvent(el, fn) {
|
||||||
|
@ -48,6 +55,7 @@ initializeWindows = function() {
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 300
|
height: 300
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
});
|
});
|
||||||
|
|
||||||
addClickEvent('preferences', function(e) {
|
addClickEvent('preferences', function(e) {
|
||||||
|
@ -87,6 +95,7 @@ initializeWindows = function() {
|
||||||
width: 600,
|
width: 600,
|
||||||
height: 130
|
height: 130
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
});
|
});
|
||||||
|
|
||||||
globalUploadLimitFN = function() {
|
globalUploadLimitFN = function() {
|
||||||
|
@ -125,6 +134,34 @@ initializeWindows = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toggleSequentialDownloadFN = function() {
|
||||||
|
var h = myTable.selectedIds();
|
||||||
|
if (h.length) {
|
||||||
|
new Request({
|
||||||
|
url: 'command/toggleSequentialDownload',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hashes: h.join("|")
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
updateTransferList();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
toggleFirstLastPiecePrioFN = function() {
|
||||||
|
var h = myTable.selectedIds();
|
||||||
|
if (h.length) {
|
||||||
|
new Request({
|
||||||
|
url: 'command/toggleFirstLastPiecePrio',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hashes: h.join("|")
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
updateTransferList();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
globalDownloadLimitFN = function() {
|
globalDownloadLimitFN = function() {
|
||||||
new MochaUI.Window({
|
new MochaUI.Window({
|
||||||
id: 'downloadLimitPage',
|
id: 'downloadLimitPage',
|
||||||
|
@ -164,10 +201,10 @@ initializeWindows = function() {
|
||||||
deleteFN = function() {
|
deleteFN = function() {
|
||||||
var h = myTable.selectedIds();
|
var h = myTable.selectedIds();
|
||||||
/*if(h.length && confirm('_(Are you sure you want to delete the selected torrents from the transfer list?)')) {
|
/*if(h.length && confirm('_(Are you sure you want to delete the selected torrents from the transfer list?)')) {
|
||||||
h.each(function(item, index){
|
h.each(function(item, index){
|
||||||
new Request({url: 'command/delete', method: 'post', data: {hash: item}}).send();
|
new Request({url: 'command/delete', method: 'post', data: {hash: item}}).send();
|
||||||
});
|
});
|
||||||
}*/
|
}*/
|
||||||
if (h.length) {
|
if (h.length) {
|
||||||
new MochaUI.Window({
|
new MochaUI.Window({
|
||||||
id: 'confirmDeletionPage',
|
id: 'confirmDeletionPage',
|
||||||
|
@ -181,6 +218,7 @@ initializeWindows = function() {
|
||||||
width: 424,
|
width: 424,
|
||||||
height: 140
|
height: 140
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,6 +239,7 @@ initializeWindows = function() {
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,6 +255,7 @@ initializeWindows = function() {
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,6 +288,7 @@ initializeWindows = function() {
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
});
|
});
|
||||||
|
updateTransferList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -276,6 +317,7 @@ initializeWindows = function() {
|
||||||
hashes: h.join("|")
|
hashes: h.join("|")
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
|
updateTransferList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,17 @@
|
||||||
ForceRecheck : function (element, ref) {
|
ForceRecheck : function (element, ref) {
|
||||||
recheckFN();
|
recheckFN();
|
||||||
},
|
},
|
||||||
UploadLimit : function (element, red) {
|
UploadLimit : function (element, ref) {
|
||||||
uploadLimitFN();
|
uploadLimitFN();
|
||||||
},
|
},
|
||||||
DownloadLimit : function (element, red) {
|
DownloadLimit : function (element, ref) {
|
||||||
downloadLimitFN();
|
downloadLimitFN();
|
||||||
|
},
|
||||||
|
SequentialDownload : function (element, ref) {
|
||||||
|
toggleSequentialDownloadFN();
|
||||||
|
},
|
||||||
|
FirstLastPiecePrio : function (element, ref) {
|
||||||
|
toggleFirstLastPiecePrioFN();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
offsets : {
|
offsets : {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue