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
|
@ -73,17 +73,21 @@ static QPair<int, int> get_file_extremity_pieces(const torrent_info& t, int file
|
|||
return qMakePair(first_piece, last_piece);
|
||||
}
|
||||
|
||||
QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h) {}
|
||||
QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
|
||||
QString QTorrentHandle::hash() const {
|
||||
QString QTorrentHandle::hash() const
|
||||
{
|
||||
return misc::toQString(torrent_handle::info_hash());
|
||||
}
|
||||
|
||||
QString QTorrentHandle::name() const {
|
||||
QString QTorrentHandle::name() const
|
||||
{
|
||||
QString name = TorrentPersistentData::getName(hash());
|
||||
if (name.isEmpty()) {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
|
@ -95,7 +99,8 @@ QString QTorrentHandle::name() const {
|
|||
return name;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::creation_date() const {
|
||||
QString QTorrentHandle::creation_date() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
|
||||
#else
|
||||
|
@ -104,7 +109,8 @@ QString QTorrentHandle::creation_date() const {
|
|||
return t ? misc::toQString(*t) : "";
|
||||
}
|
||||
|
||||
qlonglong QTorrentHandle::creation_date_unix() const {
|
||||
qlonglong QTorrentHandle::creation_date_unix() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
|
||||
#else
|
||||
|
@ -113,19 +119,23 @@ qlonglong QTorrentHandle::creation_date_unix() const {
|
|||
return t ? *t : -1;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::current_tracker() const {
|
||||
QString QTorrentHandle::current_tracker() const
|
||||
{
|
||||
return misc::toQString(status(0x0).current_tracker);
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_paused() const {
|
||||
bool QTorrentHandle::is_paused() const
|
||||
{
|
||||
return is_paused(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_queued() const {
|
||||
bool QTorrentHandle::is_queued() const
|
||||
{
|
||||
return is_queued(status(0x0));
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::total_size() const {
|
||||
size_type QTorrentHandle::total_size() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().total_size();
|
||||
#else
|
||||
|
@ -133,7 +143,8 @@ size_type QTorrentHandle::total_size() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::piece_length() const {
|
||||
size_type QTorrentHandle::piece_length() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().piece_length();
|
||||
#else
|
||||
|
@ -141,7 +152,8 @@ size_type QTorrentHandle::piece_length() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
int QTorrentHandle::num_pieces() const {
|
||||
int QTorrentHandle::num_pieces() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().num_pieces();
|
||||
#else
|
||||
|
@ -149,7 +161,8 @@ int QTorrentHandle::num_pieces() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool QTorrentHandle::first_last_piece_first() const {
|
||||
bool QTorrentHandle::first_last_piece_first() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const* t = &get_torrent_info();
|
||||
#else
|
||||
|
@ -168,14 +181,14 @@ bool QTorrentHandle::first_last_piece_first() const {
|
|||
if (index >= t->num_files()) // No media file
|
||||
return false;
|
||||
|
||||
|
||||
QPair<int, int> extremities = get_file_extremity_pieces(*t, index);
|
||||
|
||||
return (torrent_handle::piece_priority(extremities.first) == 7)
|
||||
&& (torrent_handle::piece_priority(extremities.second) == 7);
|
||||
}
|
||||
|
||||
QString QTorrentHandle::save_path() const {
|
||||
QString QTorrentHandle::save_path() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return fsutils::fromNativePath(misc::toQStringU(torrent_handle::save_path()));
|
||||
#else
|
||||
|
@ -183,11 +196,13 @@ QString QTorrentHandle::save_path() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::save_path_parsed() const {
|
||||
QString QTorrentHandle::save_path_parsed() const
|
||||
{
|
||||
QString p;
|
||||
if (has_metadata() && num_files() == 1) {
|
||||
p = firstFileSavePath();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
p = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash()));
|
||||
if (p.isEmpty())
|
||||
p = save_path();
|
||||
|
@ -195,7 +210,8 @@ QString QTorrentHandle::save_path_parsed() const {
|
|||
return p;
|
||||
}
|
||||
|
||||
QStringList QTorrentHandle::url_seeds() const {
|
||||
QStringList QTorrentHandle::url_seeds() const
|
||||
{
|
||||
QStringList res;
|
||||
try {
|
||||
const std::set<std::string> existing_seeds = torrent_handle::url_seeds();
|
||||
|
@ -213,20 +229,22 @@ QStringList QTorrentHandle::url_seeds() const {
|
|||
}
|
||||
|
||||
// get the size of the torrent without the filtered files
|
||||
size_type QTorrentHandle::actual_size() const {
|
||||
size_type QTorrentHandle::actual_size() const
|
||||
{
|
||||
return status(query_accurate_download_counters).total_wanted;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_filtered_pieces() const {
|
||||
bool QTorrentHandle::has_filtered_pieces() const
|
||||
{
|
||||
const std::vector<int> piece_priorities = torrent_handle::piece_priorities();
|
||||
foreach (const int priority, piece_priorities) {
|
||||
foreach (const int priority, piece_priorities)
|
||||
if (priority == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int QTorrentHandle::num_files() const {
|
||||
int QTorrentHandle::num_files() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().num_files();
|
||||
#else
|
||||
|
@ -234,7 +252,8 @@ int QTorrentHandle::num_files() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filename_at(unsigned int index) const {
|
||||
QString QTorrentHandle::filename_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files());
|
||||
#else
|
||||
|
@ -243,7 +262,8 @@ QString QTorrentHandle::filename_at(unsigned int index) const {
|
|||
return fsutils::fileName(filepath_at(index));
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::filesize_at(unsigned int index) const {
|
||||
size_type QTorrentHandle::filesize_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files());
|
||||
return torrent_handle::get_torrent_info().files().file_size(index);
|
||||
|
@ -253,7 +273,8 @@ size_type QTorrentHandle::filesize_at(unsigned int index) const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filepath_at(unsigned int index) const {
|
||||
QString QTorrentHandle::filepath_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return filepath_at(torrent_handle::get_torrent_info(), index);
|
||||
#else
|
||||
|
@ -261,7 +282,8 @@ QString QTorrentHandle::filepath_at(unsigned int index) const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::orig_filepath_at(unsigned int index) const {
|
||||
QString QTorrentHandle::orig_filepath_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return fsutils::fromNativePath(misc::toQStringU(torrent_handle::get_torrent_info().orig_files().file_path(index)));
|
||||
#else
|
||||
|
@ -270,11 +292,13 @@ QString QTorrentHandle::orig_filepath_at(unsigned int index) const {
|
|||
|
||||
}
|
||||
|
||||
torrent_status::state_t QTorrentHandle::state() const {
|
||||
torrent_status::state_t QTorrentHandle::state() const
|
||||
{
|
||||
return status(0x0).state;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::creator() const {
|
||||
QString QTorrentHandle::creator() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return misc::toQStringU(torrent_handle::get_torrent_info().creator());
|
||||
#else
|
||||
|
@ -282,7 +306,8 @@ QString QTorrentHandle::creator() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::comment() const {
|
||||
QString QTorrentHandle::comment() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return misc::toQStringU(torrent_handle::get_torrent_info().comment());
|
||||
#else
|
||||
|
@ -290,22 +315,24 @@ QString QTorrentHandle::comment() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_checking() const {
|
||||
bool QTorrentHandle::is_checking() const
|
||||
{
|
||||
return is_checking(status(0x0));
|
||||
}
|
||||
|
||||
// Return a list of absolute paths corresponding
|
||||
// to all files in a torrent
|
||||
QStringList QTorrentHandle::absolute_files_path() const {
|
||||
QStringList QTorrentHandle::absolute_files_path() const
|
||||
{
|
||||
QDir saveDir(save_path());
|
||||
QStringList res;
|
||||
for (int i = 0; i<num_files(); ++i) {
|
||||
for (int i = 0; i<num_files(); ++i)
|
||||
res << fsutils::expandPathAbs(saveDir.absoluteFilePath(filepath_at(i)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList QTorrentHandle::absolute_files_path_uneeded() const {
|
||||
QStringList QTorrentHandle::absolute_files_path_uneeded() const
|
||||
{
|
||||
QDir saveDir(save_path());
|
||||
QStringList res;
|
||||
std::vector<int> fp = torrent_handle::file_priorities();
|
||||
|
@ -319,19 +346,21 @@ QStringList QTorrentHandle::absolute_files_path_uneeded() const {
|
|||
return res;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_missing_files() const {
|
||||
bool QTorrentHandle::has_missing_files() const
|
||||
{
|
||||
const QStringList paths = absolute_files_path();
|
||||
foreach (const QString &path, paths) {
|
||||
foreach (const QString &path, paths)
|
||||
if (!QFile::exists(path)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int QTorrentHandle::queue_position() const {
|
||||
int QTorrentHandle::queue_position() const
|
||||
{
|
||||
return queue_position(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_seed() const {
|
||||
bool QTorrentHandle::is_seed() const
|
||||
{
|
||||
// Affected by bug http://code.rasterbar.com/libtorrent/ticket/402
|
||||
//return torrent_handle::is_seed();
|
||||
// May suffer from approximation problems
|
||||
|
@ -340,11 +369,13 @@ bool QTorrentHandle::is_seed() const {
|
|||
return is_seed(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_sequential_download() const {
|
||||
bool QTorrentHandle::is_sequential_download() const
|
||||
{
|
||||
return status(0x0).sequential_download;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::priv() const {
|
||||
bool QTorrentHandle::priv() const
|
||||
{
|
||||
if (!has_metadata())
|
||||
return false;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
|
@ -354,7 +385,8 @@ bool QTorrentHandle::priv() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::firstFileSavePath() const {
|
||||
QString QTorrentHandle::firstFileSavePath() const
|
||||
{
|
||||
Q_ASSERT(has_metadata());
|
||||
QString fsave_path = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash()));
|
||||
if (fsave_path.isEmpty())
|
||||
|
@ -379,35 +411,40 @@ QString QTorrentHandle::root_path() const
|
|||
return save_path();
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_error() const {
|
||||
bool QTorrentHandle::has_error() const
|
||||
{
|
||||
return has_error(status(0x0));
|
||||
}
|
||||
|
||||
QString QTorrentHandle::error() const {
|
||||
QString QTorrentHandle::error() const
|
||||
{
|
||||
return misc::toQString(status(0x0).error);
|
||||
}
|
||||
|
||||
void QTorrentHandle::downloading_pieces(bitfield &bf) const {
|
||||
void QTorrentHandle::downloading_pieces(bitfield &bf) const
|
||||
{
|
||||
std::vector<partial_piece_info> queue;
|
||||
torrent_handle::get_download_queue(queue);
|
||||
|
||||
std::vector<partial_piece_info>::const_iterator it = queue.begin();
|
||||
std::vector<partial_piece_info>::const_iterator itend = queue.end();
|
||||
for ( ; it!= itend; ++it) {
|
||||
for (; it!= itend; ++it)
|
||||
bf.set_bit(it->piece_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_metadata() const {
|
||||
bool QTorrentHandle::has_metadata() const
|
||||
{
|
||||
return status(0x0).has_metadata;
|
||||
}
|
||||
|
||||
void QTorrentHandle::file_progress(std::vector<size_type>& fp) const {
|
||||
void QTorrentHandle::file_progress(std::vector<size_type>& fp) const
|
||||
{
|
||||
torrent_handle::file_progress(fp, torrent_handle::piece_granularity);
|
||||
}
|
||||
|
||||
QTorrentState QTorrentHandle::torrentState() const {
|
||||
QTorrentState QTorrentHandle::torrentState() const
|
||||
{
|
||||
QTorrentState state = QTorrentState::Unknown;
|
||||
libtorrent::torrent_status s = status(torrent_handle::query_accurate_download_counters);
|
||||
|
||||
|
@ -452,17 +489,35 @@ qulonglong QTorrentHandle::eta() const
|
|||
return QBtSession::instance()->getETA(hash(), s);
|
||||
}
|
||||
|
||||
void QTorrentHandle::toggleSequentialDownload()
|
||||
{
|
||||
if (is_valid() && has_metadata()) {
|
||||
bool was_sequential = is_sequential_download();
|
||||
set_sequential_download(!was_sequential);
|
||||
if (!was_sequential)
|
||||
prioritize_first_last_piece(true);
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::toggleFirstLastPiecePrio()
|
||||
{
|
||||
if (is_valid() && has_metadata())
|
||||
prioritize_first_last_piece(!first_last_piece_first());
|
||||
}
|
||||
|
||||
//
|
||||
// Setters
|
||||
//
|
||||
|
||||
void QTorrentHandle::pause() const {
|
||||
void QTorrentHandle::pause() const
|
||||
{
|
||||
torrent_handle::auto_managed(false);
|
||||
torrent_handle::pause();
|
||||
torrent_handle::save_resume_data();
|
||||
}
|
||||
|
||||
void QTorrentHandle::resume() const {
|
||||
void QTorrentHandle::resume() const
|
||||
{
|
||||
if (has_error())
|
||||
torrent_handle::clear_error();
|
||||
|
||||
|
@ -480,27 +535,30 @@ void QTorrentHandle::resume() const {
|
|||
}
|
||||
torrent_handle::auto_managed(true);
|
||||
torrent_handle::resume();
|
||||
if (has_persistant_error && temp_path_enabled) {
|
||||
if (has_persistant_error && temp_path_enabled)
|
||||
// Force recheck
|
||||
torrent_handle::force_recheck();
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::remove_url_seed(const QString& seed) const {
|
||||
void QTorrentHandle::remove_url_seed(const QString& seed) const
|
||||
{
|
||||
torrent_handle::remove_url_seed(seed.toStdString());
|
||||
}
|
||||
|
||||
void QTorrentHandle::add_url_seed(const QString& seed) const {
|
||||
void QTorrentHandle::add_url_seed(const QString& seed) const
|
||||
{
|
||||
const std::string str_seed = seed.toStdString();
|
||||
qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str());
|
||||
torrent_handle::add_url_seed(str_seed);
|
||||
}
|
||||
|
||||
void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const {
|
||||
void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const
|
||||
{
|
||||
torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData()));
|
||||
}
|
||||
|
||||
void QTorrentHandle::move_storage(const QString& new_path) const {
|
||||
void QTorrentHandle::move_storage(const QString& new_path) const
|
||||
{
|
||||
QString hashstr = hash();
|
||||
|
||||
if (TorrentTempData::isMoveInProgress(hashstr)) {
|
||||
|
@ -525,7 +583,8 @@ void QTorrentHandle::move_storage(const QString& new_path) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool QTorrentHandle::save_torrent_file(const QString& path) const {
|
||||
bool QTorrentHandle::save_torrent_file(const QString& path) const
|
||||
{
|
||||
if (!has_metadata()) return false;
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
|
@ -553,7 +612,8 @@ bool QTorrentHandle::save_torrent_file(const QString& path) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void QTorrentHandle::file_priority(int index, int priority) const {
|
||||
void QTorrentHandle::file_priority(int index, int priority) const
|
||||
{
|
||||
vector<int> priorities = torrent_handle::file_priorities();
|
||||
if (priorities[index] != priority) {
|
||||
priorities[index] = priority;
|
||||
|
@ -561,7 +621,8 @@ void QTorrentHandle::file_priority(int index, int priority) const {
|
|||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_files(const vector<int> &files) const {
|
||||
void QTorrentHandle::prioritize_files(const vector<int> &files) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const& info = torrent_handle::get_torrent_info();
|
||||
#else
|
||||
|
@ -643,7 +704,8 @@ void QTorrentHandle::prioritize_files(const vector<int> &files) const {
|
|||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const {
|
||||
void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const
|
||||
{
|
||||
// Determine the priority to set
|
||||
int prio = b ? 7 : torrent_handle::file_priority(file_index);
|
||||
|
||||
|
@ -658,7 +720,8 @@ void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const {
|
|||
piece_priority(extremities.second, prio);
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_first_last_piece(bool b) const {
|
||||
void QTorrentHandle::prioritize_first_last_piece(bool b) const
|
||||
{
|
||||
if (!has_metadata()) return;
|
||||
// Download first and last pieces first for all media files in the torrent
|
||||
const uint nbfiles = num_files();
|
||||
|
@ -672,7 +735,8 @@ void QTorrentHandle::prioritize_first_last_piece(bool b) const {
|
|||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::rename_file(int index, const QString& name) const {
|
||||
void QTorrentHandle::rename_file(int index, const QString& name) const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << index << name;
|
||||
torrent_handle::rename_file(index, std::string(fsutils::toNativePath(name).toUtf8().constData()));
|
||||
}
|
||||
|
@ -681,39 +745,47 @@ void QTorrentHandle::rename_file(int index, const QString& name) const {
|
|||
// Operators
|
||||
//
|
||||
|
||||
bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const {
|
||||
bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const
|
||||
{
|
||||
return info_hash() == new_h.info_hash();
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_paused(const libtorrent::torrent_status &status) {
|
||||
bool QTorrentHandle::is_paused(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && !status.auto_managed;
|
||||
}
|
||||
|
||||
int QTorrentHandle::queue_position(const libtorrent::torrent_status &status) {
|
||||
int QTorrentHandle::queue_position(const libtorrent::torrent_status &status)
|
||||
{
|
||||
if (status.queue_position < 0)
|
||||
return -1;
|
||||
return status.queue_position + 1;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status) {
|
||||
bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && status.auto_managed;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_seed(const libtorrent::torrent_status &status) {
|
||||
bool QTorrentHandle::is_seed(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.state == torrent_status::finished
|
||||
|| status.state == torrent_status::seeding;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_checking(const libtorrent::torrent_status &status) {
|
||||
bool QTorrentHandle::is_checking(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.state == torrent_status::checking_files
|
||||
|| status.state == torrent_status::checking_resume_data;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_error(const libtorrent::torrent_status &status) {
|
||||
bool QTorrentHandle::has_error(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && !status.error.empty();
|
||||
}
|
||||
|
||||
float QTorrentHandle::progress(const libtorrent::torrent_status &status) {
|
||||
float QTorrentHandle::progress(const libtorrent::torrent_status &status)
|
||||
{
|
||||
if (!status.total_wanted)
|
||||
return 0.;
|
||||
if (status.total_wanted_done == status.total_wanted)
|
||||
|
@ -723,7 +795,8 @@ float QTorrentHandle::progress(const libtorrent::torrent_status &status) {
|
|||
return progress;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filepath_at(const libtorrent::torrent_info &info, unsigned int index) {
|
||||
QString QTorrentHandle::filepath_at(const libtorrent::torrent_info &info, unsigned int index)
|
||||
{
|
||||
return fsutils::fromNativePath(misc::toQStringU(info.files().file_path(index)));
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ QT_END_NAMESPACE
|
|||
class QTorrentState
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
Unknown = -1,
|
||||
|
||||
Error,
|
||||
|
@ -71,7 +72,8 @@ private:
|
|||
|
||||
// A wrapper for torrent_handle in libtorrent
|
||||
// to interact well with Qt types
|
||||
class QTorrentHandle : public libtorrent::torrent_handle {
|
||||
class QTorrentHandle: public libtorrent::torrent_handle
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
@ -126,6 +128,8 @@ public:
|
|||
void file_progress(std::vector<libtorrent::size_type>& fp) const;
|
||||
QTorrentState torrentState() const;
|
||||
qulonglong eta() const;
|
||||
void toggleSequentialDownload();
|
||||
void toggleFirstLastPiecePrio();
|
||||
|
||||
//
|
||||
// Setters
|
||||
|
|
|
@ -68,7 +68,8 @@
|
|||
using namespace libtorrent;
|
||||
|
||||
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession *_BTSession):
|
||||
QTreeView(parent), BTSession(_BTSession), main_window(main_window) {
|
||||
QTreeView(parent), BTSession(_BTSession), main_window(main_window)
|
||||
{
|
||||
|
||||
setUniformRowHeights(true);
|
||||
// Load settings
|
||||
|
@ -153,7 +154,8 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window,
|
|||
deleteHotkey = new QShortcut(QKeySequence::Delete, this, SLOT(deleteSelectedTorrents()), 0, Qt::WidgetShortcut);
|
||||
}
|
||||
|
||||
TransferListWidget::~TransferListWidget() {
|
||||
TransferListWidget::~TransferListWidget()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "ENTER";
|
||||
// Save settings
|
||||
saveSettings();
|
||||
|
@ -166,59 +168,65 @@ TransferListWidget::~TransferListWidget() {
|
|||
qDebug() << Q_FUNC_INFO << "EXIT";
|
||||
}
|
||||
|
||||
TorrentModel* TransferListWidget::getSourceModel() const {
|
||||
TorrentModel* TransferListWidget::getSourceModel() const
|
||||
{
|
||||
return listModel;
|
||||
}
|
||||
|
||||
void TransferListWidget::previewFile(QString filePath) {
|
||||
void TransferListWidget::previewFile(QString filePath)
|
||||
{
|
||||
openUrl(filePath);
|
||||
}
|
||||
|
||||
void TransferListWidget::setRefreshInterval(int t) {
|
||||
void TransferListWidget::setRefreshInterval(int t)
|
||||
{
|
||||
qDebug("Settings transfer list refresh interval to %dms", t);
|
||||
listModel->setRefreshInterval(t);
|
||||
}
|
||||
|
||||
int TransferListWidget::getRowFromHash(QString hash) const {
|
||||
int TransferListWidget::getRowFromHash(QString hash) const
|
||||
{
|
||||
return listModel->torrentRow(hash);
|
||||
}
|
||||
|
||||
inline QString TransferListWidget::getHashFromRow(int row) const {
|
||||
inline QString TransferListWidget::getHashFromRow(int row) const
|
||||
{
|
||||
return listModel->torrentHash(row);
|
||||
}
|
||||
|
||||
inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const {
|
||||
inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const
|
||||
{
|
||||
Q_ASSERT(index.isValid());
|
||||
if (index.model() == nameFilterModel)
|
||||
return nameFilterModel->mapToSource(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const {
|
||||
inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const
|
||||
{
|
||||
Q_ASSERT(index.isValid());
|
||||
Q_ASSERT(index.model() == nameFilterModel);
|
||||
return nameFilterModel->mapFromSource(index);
|
||||
}
|
||||
|
||||
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) {
|
||||
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
||||
{
|
||||
const int row = mapToSource(index).row();
|
||||
const QString hash = getHashFromRow(row);
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_valid()) return;
|
||||
int action;
|
||||
if (h.is_seed()) {
|
||||
if (h.is_seed())
|
||||
action = Preferences::instance()->getActionOnDblClOnTorrentFn();
|
||||
} else {
|
||||
else
|
||||
action = Preferences::instance()->getActionOnDblClOnTorrentDl();
|
||||
}
|
||||
|
||||
switch(action) {
|
||||
case TOGGLE_PAUSE:
|
||||
if (h.is_paused()) {
|
||||
if (h.is_paused())
|
||||
h.resume();
|
||||
} else {
|
||||
else
|
||||
h.pause();
|
||||
}
|
||||
break;
|
||||
case OPEN_DEST:
|
||||
const QString path = h.root_path();
|
||||
|
@ -226,16 +234,17 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index) {
|
|||
}
|
||||
}
|
||||
|
||||
QStringList TransferListWidget::getSelectedTorrentsHashes() const {
|
||||
QStringList TransferListWidget::getSelectedTorrentsHashes() const
|
||||
{
|
||||
QStringList hashes;
|
||||
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
foreach (const QModelIndex &index, selectedIndexes) {
|
||||
foreach (const QModelIndex &index, selectedIndexes)
|
||||
hashes << getHashFromRow(mapToSource(index).row());
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
void TransferListWidget::setSelectedTorrentsLocation() {
|
||||
void TransferListWidget::setSelectedTorrentsLocation()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.isEmpty()) return;
|
||||
QString dir;
|
||||
|
@ -254,7 +263,8 @@ void TransferListWidget::setSelectedTorrentsLocation() {
|
|||
if (!BTSession->useTemporaryFolder() || h.is_seed()) {
|
||||
if (!savePath.exists()) savePath.mkpath(savePath.absolutePath());
|
||||
h.move_storage(savePath.absolutePath());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
TorrentPersistentData::saveSavePath(h.hash(), savePath.absolutePath());
|
||||
main_window->getProperties()->updateSavePath(h);
|
||||
}
|
||||
|
@ -262,43 +272,44 @@ void TransferListWidget::setSelectedTorrentsLocation() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::startSelectedTorrents() {
|
||||
void TransferListWidget::startSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->resumeTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::startVisibleTorrents() {
|
||||
void TransferListWidget::startVisibleTorrents()
|
||||
{
|
||||
QStringList hashes;
|
||||
for (int i = 0; i<nameFilterModel->rowCount(); ++i) {
|
||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
}
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->resumeTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::pauseSelectedTorrents() {
|
||||
void TransferListWidget::pauseSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->pauseTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::pauseVisibleTorrents() {
|
||||
void TransferListWidget::pauseVisibleTorrents()
|
||||
{
|
||||
QStringList hashes;
|
||||
for (int i = 0; i<nameFilterModel->rowCount(); ++i) {
|
||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
}
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->pauseTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::deleteSelectedTorrents() {
|
||||
void TransferListWidget::deleteSelectedTorrents()
|
||||
{
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList& hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.empty()) return;
|
||||
|
@ -307,12 +318,12 @@ void TransferListWidget::deleteSelectedTorrents() {
|
|||
if (Preferences::instance()->confirmTorrentDeletion() &&
|
||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent.name()))
|
||||
return;
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->deleteTorrent(hash, delete_local_files);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::deleteVisibleTorrents() {
|
||||
void TransferListWidget::deleteVisibleTorrents()
|
||||
{
|
||||
if (nameFilterModel->rowCount() <= 0) return;
|
||||
QTorrentHandle torrent = BTSession->getTorrentHandle(getHashFromRow(0));
|
||||
bool delete_local_files = false;
|
||||
|
@ -324,12 +335,12 @@ void TransferListWidget::deleteVisibleTorrents() {
|
|||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
||||
hashes << getHashFromRow(row);
|
||||
}
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->deleteTorrent(hash, delete_local_files);
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::increasePrioSelectedTorrents() {
|
||||
void TransferListWidget::increasePrioSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
|
@ -338,9 +349,8 @@ void TransferListWidget::increasePrioSelectedTorrents() {
|
|||
foreach (const QString &hash, hashes) {
|
||||
try {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_seed()) {
|
||||
if (!h.is_seed())
|
||||
torrent_queue.push(qMakePair(h.queue_position(), h));
|
||||
}
|
||||
}catch(invalid_handle&) {}
|
||||
}
|
||||
// Increase torrents priority (starting with the ones with highest priority)
|
||||
|
@ -353,7 +363,8 @@ void TransferListWidget::increasePrioSelectedTorrents() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::decreasePrioSelectedTorrents() {
|
||||
void TransferListWidget::decreasePrioSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
|
@ -362,9 +373,8 @@ void TransferListWidget::decreasePrioSelectedTorrents() {
|
|||
foreach (const QString &hash, hashes) {
|
||||
try {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (!h.is_seed()) {
|
||||
if (!h.is_seed())
|
||||
torrent_queue.push(qMakePair(h.queue_position(), h));
|
||||
}
|
||||
}catch(invalid_handle&) {}
|
||||
}
|
||||
// Decrease torrents priority (starting with the ones with lowest priority)
|
||||
|
@ -377,29 +387,30 @@ void TransferListWidget::decreasePrioSelectedTorrents() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::topPrioSelectedTorrents() {
|
||||
void TransferListWidget::topPrioSelectedTorrents()
|
||||
{
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && !h.is_seed()) {
|
||||
if (h.is_valid() && !h.is_seed())
|
||||
h.queue_position_top();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::bottomPrioSelectedTorrents() {
|
||||
void TransferListWidget::bottomPrioSelectedTorrents()
|
||||
{
|
||||
if (main_window->getCurrentTabWidget() != this) return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && !h.is_seed()) {
|
||||
if (h.is_valid() && !h.is_seed())
|
||||
h.queue_position_bottom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::copySelectedMagnetURIs() const {
|
||||
void TransferListWidget::copySelectedMagnetURIs() const
|
||||
{
|
||||
QStringList magnet_uris;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
|
@ -410,12 +421,14 @@ void TransferListWidget::copySelectedMagnetURIs() const {
|
|||
qApp->clipboard()->setText(magnet_uris.join("\n"));
|
||||
}
|
||||
|
||||
void TransferListWidget::hidePriorityColumn(bool hide) {
|
||||
void TransferListWidget::hidePriorityColumn(bool hide)
|
||||
{
|
||||
qDebug("hidePriorityColumn(%d)", hide);
|
||||
setColumnHidden(TorrentModelItem::TR_PRIORITY, hide);
|
||||
}
|
||||
|
||||
void TransferListWidget::openSelectedTorrentsFolder() const {
|
||||
void TransferListWidget::openSelectedTorrentsFolder() const
|
||||
{
|
||||
QSet<QString> pathsList;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
|
@ -431,17 +444,18 @@ void TransferListWidget::openSelectedTorrentsFolder() const {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::previewSelectedTorrents() {
|
||||
void TransferListWidget::previewSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata()) {
|
||||
if (h.is_valid() && h.has_metadata())
|
||||
new PreviewSelect(this, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setDlLimitSelectedTorrents() {
|
||||
void TransferListWidget::setDlLimitSelectedTorrents()
|
||||
{
|
||||
QList<QTorrentHandle> selected_torrents;
|
||||
bool first = true;
|
||||
bool all_same_limit = true;
|
||||
|
@ -451,14 +465,13 @@ void TransferListWidget::setDlLimitSelectedTorrents() {
|
|||
if (h.is_valid() && !h.is_seed()) {
|
||||
selected_torrents << h;
|
||||
// Determine current limit for selected torrents
|
||||
if (first) {
|
||||
if (first)
|
||||
first = false;
|
||||
} else {
|
||||
else
|
||||
if (all_same_limit && h.download_limit() != selected_torrents.first().download_limit())
|
||||
all_same_limit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selected_torrents.empty()) return;
|
||||
|
||||
bool ok = false;
|
||||
|
@ -474,7 +487,8 @@ void TransferListWidget::setDlLimitSelectedTorrents() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setUpLimitSelectedTorrents() {
|
||||
void TransferListWidget::setUpLimitSelectedTorrents()
|
||||
{
|
||||
QList<QTorrentHandle> selected_torrents;
|
||||
bool first = true;
|
||||
bool all_same_limit = true;
|
||||
|
@ -484,14 +498,13 @@ void TransferListWidget::setUpLimitSelectedTorrents() {
|
|||
if (h.is_valid()) {
|
||||
selected_torrents << h;
|
||||
// Determine current limit for selected torrents
|
||||
if (first) {
|
||||
if (first)
|
||||
first = false;
|
||||
} else {
|
||||
else
|
||||
if (all_same_limit && h.upload_limit() != selected_torrents.first().upload_limit())
|
||||
all_same_limit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selected_torrents.empty()) return;
|
||||
|
||||
bool ok = false;
|
||||
|
@ -507,7 +520,8 @@ void TransferListWidget::setUpLimitSelectedTorrents() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setMaxRatioSelectedTorrents() {
|
||||
void TransferListWidget::setMaxRatioSelectedTorrents()
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
if (hashes.isEmpty())
|
||||
return;
|
||||
|
@ -515,7 +529,8 @@ void TransferListWidget::setMaxRatioSelectedTorrents() {
|
|||
qreal currentMaxRatio;
|
||||
if (hashes.count() == 1) {
|
||||
currentMaxRatio = BTSession->getMaxRatioPerTorrent(hashes.first(), &useGlobalValue);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
useGlobalValue = true;
|
||||
currentMaxRatio = BTSession->getGlobalMaxRatio();
|
||||
}
|
||||
|
@ -530,18 +545,19 @@ void TransferListWidget::setMaxRatioSelectedTorrents() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::recheckSelectedTorrents() {
|
||||
void TransferListWidget::recheckSelectedTorrents()
|
||||
{
|
||||
QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Recheck confirmation"), tr("Are you sure you want to recheck the selected torrent(s)?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
if (ret != QMessageBox::Yes)
|
||||
return;
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
foreach (const QString &hash, hashes)
|
||||
BTSession->recheckTorrent(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// hide/show columns menu
|
||||
void TransferListWidget::displayDLHoSMenu(const QPoint&) {
|
||||
void TransferListWidget::displayDLHoSMenu(const QPoint&)
|
||||
{
|
||||
QMenu hideshowColumn(this);
|
||||
hideshowColumn.setTitle(tr("Column visibility"));
|
||||
QList<QAction*> actions;
|
||||
|
@ -579,40 +595,36 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&) {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const {
|
||||
void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata()) {
|
||||
if (h.is_valid() && h.has_metadata())
|
||||
h.super_seeding(!h.status(0).super_seeding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const {
|
||||
void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const
|
||||
{
|
||||
const QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata()) {
|
||||
bool was_sequential = h.is_sequential_download();
|
||||
h.set_sequential_download(!was_sequential);
|
||||
if (!was_sequential)
|
||||
h.prioritize_first_last_piece(true);
|
||||
}
|
||||
h.toggleSequentialDownload();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::toggleSelectedFirstLastPiecePrio() const {
|
||||
void TransferListWidget::toggleSelectedFirstLastPiecePrio() const
|
||||
{
|
||||
QStringList hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if (h.is_valid() && h.has_metadata()) {
|
||||
h.prioritize_first_last_piece(!h.first_last_piece_first());
|
||||
}
|
||||
h.toggleFirstLastPiecePrio();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::askNewLabelForSelection() {
|
||||
void TransferListWidget::askNewLabelForSelection()
|
||||
{
|
||||
// Ask for label
|
||||
bool ok;
|
||||
bool invalid;
|
||||
|
@ -622,7 +634,8 @@ void TransferListWidget::askNewLabelForSelection() {
|
|||
if (ok && !label.isEmpty()) {
|
||||
if (fsutils::isValidFileSystemName(label)) {
|
||||
setSelectionLabel(label);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
QMessageBox::warning(this, tr("Invalid label name"), tr("Please don't use any special characters in the label name."));
|
||||
invalid = true;
|
||||
}
|
||||
|
@ -630,7 +643,8 @@ void TransferListWidget::askNewLabelForSelection() {
|
|||
} while(invalid);
|
||||
}
|
||||
|
||||
bool TransferListWidget::openUrl(const QString &_path) const {
|
||||
bool TransferListWidget::openUrl(const QString &_path) const
|
||||
{
|
||||
const QString path = fsutils::fromNativePath(_path);
|
||||
// Hack to access samba shares with QDesktopServices::openUrl
|
||||
if (path.startsWith("//"))
|
||||
|
@ -639,7 +653,8 @@ bool TransferListWidget::openUrl(const QString &_path) const {
|
|||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
|
||||
void TransferListWidget::renameSelectedTorrent() {
|
||||
void TransferListWidget::renameSelectedTorrent()
|
||||
{
|
||||
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
if (selectedIndexes.size() != 1) return;
|
||||
if (!selectedIndexes.first().isValid()) return;
|
||||
|
@ -657,7 +672,8 @@ void TransferListWidget::renameSelectedTorrent() {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::setSelectionLabel(QString label) {
|
||||
void TransferListWidget::setSelectionLabel(QString label)
|
||||
{
|
||||
const QStringList& hashes = getSelectedTorrentsHashes();
|
||||
foreach (const QString &hash, hashes) {
|
||||
Q_ASSERT(!hash.isEmpty());
|
||||
|
@ -670,7 +686,8 @@ void TransferListWidget::setSelectionLabel(QString label) {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::removeLabelFromRows(QString label) {
|
||||
void TransferListWidget::removeLabelFromRows(QString label)
|
||||
{
|
||||
for (int i = 0; i<listModel->rowCount(); ++i) {
|
||||
if (listModel->data(listModel->index(i, TorrentModelItem::TR_LABEL)) == label) {
|
||||
const QString hash = getHashFromRow(i);
|
||||
|
@ -682,7 +699,8 @@ void TransferListWidget::removeLabelFromRows(QString label) {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::displayListMenu(const QPoint&) {
|
||||
void TransferListWidget::displayListMenu(const QPoint&)
|
||||
{
|
||||
QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||
if (selectedIndexes.size() == 0)
|
||||
return;
|
||||
|
@ -754,25 +772,23 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
if (first) {
|
||||
sequential_download_mode = h.is_sequential_download();
|
||||
prioritize_first_last = h.first_last_piece_first();
|
||||
} else {
|
||||
if (sequential_download_mode != h.is_sequential_download()) {
|
||||
}
|
||||
else {
|
||||
if (sequential_download_mode != h.is_sequential_download())
|
||||
all_same_sequential_download_mode = false;
|
||||
}
|
||||
if (prioritize_first_last != h.first_last_piece_first()) {
|
||||
if (prioritize_first_last != h.first_last_piece_first())
|
||||
all_same_prio_firstlast = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!one_not_seed && all_same_super_seeding && h.has_metadata()) {
|
||||
if (first) {
|
||||
super_seeding_mode = h.status(0).super_seeding;
|
||||
} else {
|
||||
if (super_seeding_mode != h.status(0).super_seeding) {
|
||||
}
|
||||
else if (super_seeding_mode != h.status(0).super_seeding)
|
||||
all_same_super_seeding = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (h.is_paused()) {
|
||||
|
@ -780,15 +796,15 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
listMenu.addAction(&actionStart);
|
||||
has_start = true;
|
||||
}
|
||||
}else{
|
||||
}
|
||||
else {
|
||||
if (!has_pause) {
|
||||
listMenu.addAction(&actionPause);
|
||||
has_pause = true;
|
||||
}
|
||||
}
|
||||
if (h.has_metadata() && BTSession->isFilePreviewPossible(hash) && !has_preview) {
|
||||
if (h.has_metadata() && BTSession->isFilePreviewPossible(hash) && !has_preview)
|
||||
has_preview = true;
|
||||
}
|
||||
first = false;
|
||||
if (has_pause && has_start && has_preview && one_not_seed) break;
|
||||
}
|
||||
|
@ -806,9 +822,8 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("list-add"), tr("New...", "New label..."));
|
||||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset label"));
|
||||
labelMenu->addSeparator();
|
||||
foreach (const QString &label, customLabels) {
|
||||
foreach (const QString &label, customLabels)
|
||||
labelActions << labelMenu->addAction(IconProvider::instance()->getIcon("inode-directory"), label);
|
||||
}
|
||||
listMenu.addSeparator();
|
||||
if (one_not_seed)
|
||||
listMenu.addAction(&actionSet_download_limit);
|
||||
|
@ -864,7 +879,8 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
if (i == 0) {
|
||||
// New Label
|
||||
askNewLabelForSelection();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
QString label = "";
|
||||
if (i > 1)
|
||||
label = customLabels.at(i - 2);
|
||||
|
@ -875,7 +891,8 @@ void TransferListWidget::displayListMenu(const QPoint&) {
|
|||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::currentChanged(const QModelIndex& current, const QModelIndex&) {
|
||||
void TransferListWidget::currentChanged(const QModelIndex& current, const QModelIndex&)
|
||||
{
|
||||
qDebug("CURRENT CHANGED");
|
||||
QTorrentHandle h;
|
||||
if (current.isValid()) {
|
||||
|
@ -887,20 +904,24 @@ void TransferListWidget::currentChanged(const QModelIndex& current, const QModel
|
|||
emit currentTorrentChanged(h);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyLabelFilterAll() {
|
||||
void TransferListWidget::applyLabelFilterAll()
|
||||
{
|
||||
nameFilterModel->disableLabelFilter();
|
||||
}
|
||||
|
||||
void TransferListWidget::applyLabelFilter(QString label) {
|
||||
void TransferListWidget::applyLabelFilter(QString label)
|
||||
{
|
||||
qDebug("Applying Label filter: %s", qPrintable(label));
|
||||
nameFilterModel->setLabelFilter(label);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyNameFilter(const QString& name) {
|
||||
void TransferListWidget::applyNameFilter(const QString& name)
|
||||
{
|
||||
nameFilterModel->setFilterRegExp(QRegExp(QRegExp::escape(name), Qt::CaseInsensitive));
|
||||
}
|
||||
|
||||
void TransferListWidget::applyStatusFilter(int f) {
|
||||
void TransferListWidget::applyStatusFilter(int f)
|
||||
{
|
||||
nameFilterModel->setStatusFilter((TorrentFilter::TorrentFilter)f);
|
||||
// Select first item if nothing is selected
|
||||
if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) {
|
||||
|
@ -917,9 +938,8 @@ void TransferListWidget::saveSettings()
|
|||
bool TransferListWidget::loadSettings()
|
||||
{
|
||||
bool ok = header()->restoreState(Preferences::instance()->getTransHeaderState());
|
||||
if (!ok) {
|
||||
if (!ok)
|
||||
header()->resizeSection(0, 200); // Default
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ class QSortFilterProxyModel;
|
|||
class QStandardItemModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class TransferListWidget: public QTreeView {
|
||||
class TransferListWidget: public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -47,13 +47,11 @@ HttpResponse AbstractRequestHandler::run()
|
|||
{
|
||||
response_ = HttpResponse();
|
||||
|
||||
if (isBanned())
|
||||
{
|
||||
if (isBanned()) {
|
||||
status(403, "Forbidden");
|
||||
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts."), CONTENT_TYPE_TXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
processRequest();
|
||||
}
|
||||
|
||||
|
@ -94,9 +92,6 @@ void AbstractRequestHandler::print_impl(const QByteArray& data, const QString& t
|
|||
if (!response_.headers.contains(HEADER_CONTENT_TYPE))
|
||||
response_.headers[HEADER_CONTENT_TYPE] = type;
|
||||
|
||||
if (type.indexOf("image") > -1)
|
||||
response_.headers[HEADER_CACHE_CONTROL] = "max-age=3000000";
|
||||
|
||||
response_.content += data;
|
||||
}
|
||||
|
||||
|
@ -105,8 +100,7 @@ void AbstractRequestHandler::printFile(const QString& path)
|
|||
QByteArray data;
|
||||
QString type;
|
||||
|
||||
if (!app_->readFile(path, data, type))
|
||||
{
|
||||
if (!app_->readFile(path, data, type)) {
|
||||
status(404, "Not Found");
|
||||
return;
|
||||
}
|
||||
|
@ -121,8 +115,7 @@ void AbstractRequestHandler::sessionInitialize()
|
|||
|
||||
void AbstractRequestHandler::sessionStart()
|
||||
{
|
||||
if (app_->sessionStart(this))
|
||||
{
|
||||
if (app_->sessionStart(this)) {
|
||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
||||
cookie.setPath("/");
|
||||
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
||||
|
@ -131,18 +124,15 @@ void AbstractRequestHandler::sessionStart()
|
|||
|
||||
void AbstractRequestHandler::sessionEnd()
|
||||
{
|
||||
if (sessionActive())
|
||||
{
|
||||
if (sessionActive()) {
|
||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8());
|
||||
cookie.setPath("/");
|
||||
cookie.setExpirationDate(QDateTime::currentDateTime());
|
||||
|
||||
if (app_->sessionEnd(this))
|
||||
{
|
||||
header(HEADER_SET_COOKIE, cookie.toRawForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AbstractRequestHandler::isBanned() const
|
||||
{
|
||||
|
@ -168,8 +158,7 @@ QString AbstractRequestHandler::saveTmpFile(const QByteArray &data)
|
|||
{
|
||||
QTemporaryFile tmpfile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent"));
|
||||
tmpfile.setAutoRemove(false);
|
||||
if (tmpfile.open())
|
||||
{
|
||||
if (tmpfile.open()) {
|
||||
tmpfile.write(data);
|
||||
tmpfile.close();
|
||||
return tmpfile.fileName();
|
||||
|
|
|
@ -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_ETA[] = "eta";
|
||||
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
|
||||
static const char KEY_TRACKER_URL[] = "url";
|
||||
|
@ -211,6 +213,12 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
|||
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio;
|
||||
ret[KEY_TORRENT_STATE] = h.torrentState().toString();
|
||||
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;
|
||||
}
|
||||
|
@ -294,8 +302,9 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
|
|||
tracker_dict[KEY_TRACKER_URL] = tracker_url;
|
||||
const TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||
QString status;
|
||||
if (it->verified)
|
||||
if (it->verified) {
|
||||
status = tr("Working");
|
||||
}
|
||||
else {
|
||||
if (it->updating && it->fails == 0)
|
||||
status = tr("Updating...");
|
||||
|
|
|
@ -62,6 +62,7 @@ const QString SCOPE_THEME = "theme";
|
|||
const QString DEFAULT_ACTION = "index";
|
||||
const QString WEBUI_ACTION = "webui";
|
||||
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
|
||||
|
||||
|
@ -99,6 +100,8 @@ QMap<QString, QMap<QString, RequestHandler::Action> > RequestHandler::initialize
|
|||
ADD_ACTION(command, getTorrentDlLimit);
|
||||
ADD_ACTION(command, setTorrentUpLimit);
|
||||
ADD_ACTION(command, setTorrentDlLimit);
|
||||
ADD_ACTION(command, toggleSequentialDownload);
|
||||
ADD_ACTION(command, toggleFirstLastPiecePrio);
|
||||
ADD_ACTION(command, delete);
|
||||
ADD_ACTION(command, deletePerm);
|
||||
ADD_ACTION(command, increasePrio);
|
||||
|
@ -178,12 +181,14 @@ void RequestHandler::action_public_theme()
|
|||
qDebug() << Q_FUNC_INFO << "There icon:" << url;
|
||||
|
||||
printFile(url);
|
||||
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH);
|
||||
}
|
||||
|
||||
void RequestHandler::action_public_images()
|
||||
{
|
||||
const QString path = ":/Icons/" + args_.join("/");
|
||||
printFile(path);
|
||||
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH);
|
||||
}
|
||||
|
||||
// GET params:
|
||||
|
@ -423,6 +428,30 @@ void RequestHandler::action_command_setTorrentDlLimit()
|
|||
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()
|
||||
{
|
||||
QStringList hashes = request().posts["hashes"].split("|");
|
||||
|
|
|
@ -74,6 +74,8 @@ private:
|
|||
void action_command_getTorrentDlLimit();
|
||||
void action_command_setTorrentUpLimit();
|
||||
void action_command_setTorrentDlLimit();
|
||||
void action_command_toggleSequentialDownload();
|
||||
void action_command_toggleFirstLastPiecePrio();
|
||||
void action_command_delete();
|
||||
void action_command_deletePerm();
|
||||
void action_command_increasePrio();
|
||||
|
|
|
@ -83,8 +83,10 @@
|
|||
<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>
|
||||
<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="decreasePrioButton"><img class="mochaToolButton" title="_(Decrease priority)" src="theme/go-down" alt="_(Decrease priority)" 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="topPrioButton"><img class="mochaToolButton" title="_(Move to top)" src="theme/go-top" alt="_(Move to top)" width="24" height="24" onload="fixPNG(this)"/></a>
|
||||
</span>
|
||||
<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>
|
||||
|
@ -96,7 +98,8 @@
|
|||
<li><a href="#Start"><img src="theme/media-playback-start" alt="_(Resume)"/> _(Resume)</a></li>
|
||||
<li><a href="#Pause"><img src="theme/media-playback-pause" alt="_(Pause)"/> _(Pause)</a></li>
|
||||
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="_(Delete)"/> _(Delete)</a></li>
|
||||
<li class="separator"><a href="#priority" class="arrow-right">_(Priority)</a>
|
||||
<li id="queueingMenuItems" class="separator">
|
||||
<a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> _(Priority)</a>
|
||||
<ul>
|
||||
<li><a href="#prioTop"><img src="theme/go-top" alt="_(Move to top)"/> _(Move to top)</a></li>
|
||||
<li><a href="#prioUp"><img src="theme/go-up" alt="_(Move up)"/> _(Move up)</a></li>
|
||||
|
@ -106,6 +109,8 @@
|
|||
</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="#UploadLimit"><img src="images/skin/seeding.png" alt="_(Limit upload rate...)"/> _(Limit upload rate...)</a></li>
|
||||
<li class="separator"><a href="#SequentialDownload"><img src="theme/checked" alt="_(Download in sequential order)"/> _(Download in sequential order)</a></li>
|
||||
<li><a href="#FirstLastPiecePrio"><img src="theme/checked" alt="_(Download first and last piece first)"/> _(Download first and last piece first)</a></li>
|
||||
<li class="separator"><a href="#ForceRecheck"><img src="theme/document-edit-verify" alt="_(Force recheck)"/> _(Force recheck)</a></li>
|
||||
</ul>
|
||||
<div id="desktopFooterWrapper">
|
||||
|
|
|
@ -6,12 +6,3 @@
|
|||
<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>
|
||||
</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,62 +24,6 @@
|
|||
|
||||
myTable = new dynamicTable();
|
||||
|
||||
window.addEvent('load', function () {
|
||||
|
||||
var saveColumnSizes = function () {
|
||||
var filters_width = $('Filters').getSize().x;
|
||||
var properties_height = $('propertiesPanel').getSize().y;
|
||||
localStorage.setItem('filters_width', filters_width);
|
||||
localStorage.setItem('properties_height', properties_height);
|
||||
}
|
||||
|
||||
/*MochaUI.Desktop = new MochaUI.Desktop();
|
||||
MochaUI.Desktop.desktop.setStyles({
|
||||
'background': '#fff',
|
||||
'visibility': 'visible'
|
||||
});*/
|
||||
MochaUI.Desktop.initialize();
|
||||
|
||||
var filt_w = localStorage.getItem('filters_width');
|
||||
if ($defined(filt_w))
|
||||
filt_w = filt_w.toInt();
|
||||
else
|
||||
filt_w = 120;
|
||||
new MochaUI.Column({
|
||||
id : 'filtersColumn',
|
||||
placement : 'left',
|
||||
onResize : saveColumnSizes,
|
||||
width : filt_w,
|
||||
resizeLimit : [100, 300]
|
||||
});
|
||||
new MochaUI.Column({
|
||||
id : 'mainColumn',
|
||||
placement : 'main',
|
||||
width : null,
|
||||
resizeLimit : [100, 300]
|
||||
});
|
||||
MochaUI.Desktop.setDesktopSize();
|
||||
new MochaUI.Panel({
|
||||
id : 'Filters',
|
||||
title : 'Panel',
|
||||
header : false,
|
||||
padding : {
|
||||
top : 0,
|
||||
right : 0,
|
||||
bottom : 0,
|
||||
left : 0
|
||||
},
|
||||
loadMethod : 'xhr',
|
||||
contentURL : 'filters.html',
|
||||
column : 'filtersColumn',
|
||||
height : 300
|
||||
});
|
||||
initializeWindows();
|
||||
|
||||
var speedInTitle = localStorage.getItem('speed_in_browser_title_bar') == "true";
|
||||
if (!speedInTitle)
|
||||
$('speedInBrowserTitleBarLink').firstChild.style.opacity = '0';
|
||||
|
||||
var stateToImg = function (state) {
|
||||
if (state == "pausedUP" || state == "pausedDL") {
|
||||
state = "paused";
|
||||
|
@ -95,48 +39,10 @@ window.addEvent('load', function () {
|
|||
return 'images/skin/' + state + '.png';
|
||||
};
|
||||
|
||||
var loadTransferInfoTimer;
|
||||
var loadTransferInfo = function () {
|
||||
var url = 'json/transferInfo';
|
||||
var request = new Request.JSON({
|
||||
url : url,
|
||||
noCache : true,
|
||||
method : 'get',
|
||||
onFailure : function () {
|
||||
$('error_div').set('html', '_(qBittorrent client is not reachable)');
|
||||
loadTransferInfoTimer = loadTransferInfo.delay(4000);
|
||||
},
|
||||
onSuccess : function (info) {
|
||||
if (info) {
|
||||
$("DlInfos").set('html', "_(D: %1 - T: %2)"
|
||||
.replace("%1", friendlyUnit(info.dl_info_speed, true))
|
||||
.replace("%2", friendlyUnit(info.dl_info_data, false)));
|
||||
$("UpInfos").set('html', "_(U: %1 - T: %2)"
|
||||
.replace("%1", friendlyUnit(info.up_info_speed, true))
|
||||
.replace("%2", friendlyUnit(info.up_info_data, false)));
|
||||
if (speedInTitle)
|
||||
document.title = "_(D:%1 U:%2)".replace("%1", friendlyUnit(info.dl_info_speed, true)).replace("%2", friendlyUnit(info.up_info_speed, true));
|
||||
else
|
||||
document.title = "_(qBittorrent web User Interface)";
|
||||
loadTransferInfoTimer = loadTransferInfo.delay(3000);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
filter = getLocalStorageItem('selected_filter', 'all');
|
||||
|
||||
var updateTransferInfo = function() {
|
||||
clearTimeout(loadTransferInfoTimer);
|
||||
loadTransferInfoTimer = loadTransferInfo();
|
||||
}
|
||||
|
||||
// Start fetching data now
|
||||
loadTransferInfo();
|
||||
|
||||
$('DlInfos').addEvent('click', globalDownloadLimitFN);
|
||||
$('UpInfos').addEvent('click', globalUploadLimitFN);
|
||||
|
||||
var ajaxfnTimer;
|
||||
var ajaxfn = function () {
|
||||
var loadTorrentsInfoTimer;
|
||||
var loadTorrentsInfo = function () {
|
||||
var queueing_enabled = false;
|
||||
var url = new URI('json/torrents');
|
||||
url.setData('filter', filter);
|
||||
|
@ -148,7 +54,7 @@ window.addEvent('load', function () {
|
|||
method : 'get',
|
||||
onFailure : function () {
|
||||
$('error_div').set('html', '_(qBittorrent client is not reachable)');
|
||||
ajaxfnTimer = ajaxfn.delay(2000);
|
||||
loadTorrentsInfoTimer = loadTorrentsInfo.delay(2000);
|
||||
},
|
||||
onSuccess : function (events) {
|
||||
$('error_div').set('html', '');
|
||||
|
@ -193,14 +99,21 @@ window.addEvent('load', function () {
|
|||
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, event.state, pos);
|
||||
myTable.insertRow(event.hash, row, data, attrs, pos);
|
||||
} else {
|
||||
// Update torrent data
|
||||
myTable.updateRow(event.hash, row, data, event.state, pos);
|
||||
myTable.updateRow(event.hash, row, data, attrs, pos);
|
||||
}
|
||||
|
||||
pos++;
|
||||
|
@ -213,24 +126,142 @@ window.addEvent('load', function () {
|
|||
});
|
||||
if (queueing_enabled) {
|
||||
$('queueingButtons').removeClass('invisible');
|
||||
$('queueingMenuItems').removeClass('invisible');
|
||||
myTable.showPriority();
|
||||
} else {
|
||||
$('queueingButtons').addClass('invisible');
|
||||
$('queueingMenuItems').addClass('invisible');
|
||||
myTable.hidePriority();
|
||||
}
|
||||
|
||||
myTable.altRow();
|
||||
}
|
||||
ajaxfnTimer = ajaxfn.delay(1500);
|
||||
loadTorrentsInfoTimer = loadTorrentsInfo.delay(1500);
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
|
||||
var updateTransferList = function() {
|
||||
clearTimeout(ajaxfnTimer);
|
||||
ajaxfnTimer = ajaxfn();
|
||||
clearTimeout(loadTorrentsInfoTimer);
|
||||
loadTorrentsInfoTimer = loadTorrentsInfo();
|
||||
}
|
||||
|
||||
window.addEvent('load', function () {
|
||||
|
||||
var saveColumnSizes = function () {
|
||||
var filters_width = $('Filters').getSize().x;
|
||||
var properties_height = $('propertiesPanel').getSize().y;
|
||||
localStorage.setItem('filters_width', filters_width);
|
||||
localStorage.setItem('properties_height', properties_height);
|
||||
}
|
||||
|
||||
/*MochaUI.Desktop = new MochaUI.Desktop();
|
||||
MochaUI.Desktop.desktop.setStyles({
|
||||
'background': '#fff',
|
||||
'visibility': 'visible'
|
||||
});*/
|
||||
MochaUI.Desktop.initialize();
|
||||
|
||||
var filt_w = localStorage.getItem('filters_width');
|
||||
if ($defined(filt_w))
|
||||
filt_w = filt_w.toInt();
|
||||
else
|
||||
filt_w = 120;
|
||||
new MochaUI.Column({
|
||||
id : 'filtersColumn',
|
||||
placement : 'left',
|
||||
onResize : saveColumnSizes,
|
||||
width : filt_w,
|
||||
resizeLimit : [100, 300]
|
||||
});
|
||||
new MochaUI.Column({
|
||||
id : 'mainColumn',
|
||||
placement : 'main',
|
||||
width : null,
|
||||
resizeLimit : [100, 300]
|
||||
});
|
||||
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({
|
||||
id : 'Filters',
|
||||
title : 'Panel',
|
||||
header : false,
|
||||
padding : {
|
||||
top : 0,
|
||||
right : 0,
|
||||
bottom : 0,
|
||||
left : 0
|
||||
},
|
||||
loadMethod : 'xhr',
|
||||
contentURL : 'filters.html',
|
||||
onContentLoaded : function () {
|
||||
setFilter(filter);
|
||||
},
|
||||
column : 'filtersColumn',
|
||||
height : 300
|
||||
});
|
||||
initializeWindows();
|
||||
|
||||
var speedInTitle = localStorage.getItem('speed_in_browser_title_bar') == "true";
|
||||
if (!speedInTitle)
|
||||
$('speedInBrowserTitleBarLink').firstChild.style.opacity = '0';
|
||||
|
||||
var loadTransferInfoTimer;
|
||||
var loadTransferInfo = function () {
|
||||
var url = 'json/transferInfo';
|
||||
var request = new Request.JSON({
|
||||
url : url,
|
||||
noCache : true,
|
||||
method : 'get',
|
||||
onFailure : function () {
|
||||
$('error_div').set('html', '_(qBittorrent client is not reachable)');
|
||||
loadTransferInfoTimer = loadTransferInfo.delay(4000);
|
||||
},
|
||||
onSuccess : function (info) {
|
||||
if (info) {
|
||||
$("DlInfos").set('html', "_(D: %1 - T: %2)"
|
||||
.replace("%1", friendlyUnit(info.dl_info_speed, true))
|
||||
.replace("%2", friendlyUnit(info.dl_info_data, false)));
|
||||
$("UpInfos").set('html', "_(U: %1 - T: %2)"
|
||||
.replace("%1", friendlyUnit(info.up_info_speed, true))
|
||||
.replace("%2", friendlyUnit(info.up_info_data, false)));
|
||||
if (speedInTitle)
|
||||
document.title = "_(D:%1 U:%2)".replace("%1", friendlyUnit(info.dl_info_speed, true)).replace("%2", friendlyUnit(info.up_info_speed, true));
|
||||
else
|
||||
document.title = "_(qBittorrent web User Interface)";
|
||||
loadTransferInfoTimer = loadTransferInfo.delay(3000);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
|
||||
var updateTransferInfo = function() {
|
||||
clearTimeout(loadTransferInfoTimer);
|
||||
loadTransferInfoTimer = loadTransferInfo();
|
||||
}
|
||||
|
||||
// Start fetching data now
|
||||
loadTransferInfo();
|
||||
|
||||
$('DlInfos').addEvent('click', globalDownloadLimitFN);
|
||||
$('UpInfos').addEvent('click', globalUploadLimitFN);
|
||||
|
||||
setSortedColumn = function (column) {
|
||||
myTable.setSortedColumn(column);
|
||||
updateTransferList();
|
||||
|
@ -288,22 +319,6 @@ window.addEvent('load', function () {
|
|||
column : 'mainColumn',
|
||||
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() {
|
||||
|
|
|
@ -127,9 +127,89 @@ var ContextMenu = new Class({
|
|||
}.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: function(trigger) {
|
||||
//this.menu.fade('in');
|
||||
this.updateMenuItems();
|
||||
this.fx.start(1);
|
||||
this.fireEvent('show');
|
||||
this.shown = true;
|
||||
|
@ -147,15 +227,21 @@ var ContextMenu = new Class({
|
|||
return this;
|
||||
},
|
||||
|
||||
//disable an item
|
||||
disableItem: function(item) {
|
||||
this.menu.getElements('a[href$=' + item + ']').addClass('disabled');
|
||||
setItemChecked: function(item, checked) {
|
||||
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
||||
checked ? '1' : '0';
|
||||
return this;
|
||||
},
|
||||
|
||||
//enable an item
|
||||
enableItem: function(item) {
|
||||
this.menu.getElements('a[href$=' + item + ']').removeClass('disabled');
|
||||
//hide an item
|
||||
hideItem: function(item) {
|
||||
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;
|
||||
},
|
||||
|
||||
|
|
|
@ -42,18 +42,20 @@ var dynamicTable = new Class({
|
|||
this.priority_hidden = false;
|
||||
this.progressIndex = progressIndex;
|
||||
this.context_menu = context_menu;
|
||||
this.table.sortedColumn = 'name'; // Default is NAME
|
||||
this.table.reverseSort = false;
|
||||
this.table.sortedColumn = getLocalStorageItem('sorted_column', 'name');
|
||||
this.table.reverseSort = getLocalStorageItem('reverse_sort', 'false');;
|
||||
},
|
||||
|
||||
setSortedColumn : function (column) {
|
||||
if (column != this.table.sortedColumn) {
|
||||
this.table.sortedColumn = column;
|
||||
this.table.reverseSort = false;
|
||||
this.table.reverseSort = 'false';
|
||||
} else {
|
||||
// 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 () {
|
||||
|
@ -100,11 +102,13 @@ var dynamicTable = new Class({
|
|||
this.priority_hidden = false;
|
||||
},
|
||||
|
||||
insertRow : function (id, row, data, status, pos) {
|
||||
insertRow : function (id, row, data, attrs, pos) {
|
||||
if (this.rows.has(id)) {
|
||||
return;
|
||||
}
|
||||
var tr = new Element('tr');
|
||||
for (var a in attrs)
|
||||
tr.set(a, attrs[a]);
|
||||
tr.addClass("menu-target");
|
||||
this.rows.set(id, tr);
|
||||
for (var i = 0; i < row.length; i++) {
|
||||
|
@ -244,12 +248,14 @@ var dynamicTable = new Class({
|
|||
}, this);
|
||||
},
|
||||
|
||||
updateRow : function (id, row, data, status, newpos) {
|
||||
updateRow : function (id, row, data, attrs, newpos) {
|
||||
if (!this.rows.has(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var tr = this.rows.get(id);
|
||||
for (var a in attrs)
|
||||
tr.set(a, attrs[a]);
|
||||
var tds = tr.getElements('td');
|
||||
for (var i = 0; i < row.length; i++) {
|
||||
if (i == 1)
|
||||
|
|
|
@ -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() {
|
||||
|
||||
function addClickEvent(el, fn) {
|
||||
|
@ -48,6 +55,7 @@ initializeWindows = function() {
|
|||
width: 500,
|
||||
height: 300
|
||||
});
|
||||
updateTransferList();
|
||||
});
|
||||
|
||||
addClickEvent('preferences', function(e) {
|
||||
|
@ -87,6 +95,7 @@ initializeWindows = function() {
|
|||
width: 600,
|
||||
height: 130
|
||||
});
|
||||
updateTransferList();
|
||||
});
|
||||
|
||||
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() {
|
||||
new MochaUI.Window({
|
||||
id: 'downloadLimitPage',
|
||||
|
@ -181,6 +218,7 @@ initializeWindows = function() {
|
|||
width: 424,
|
||||
height: 140
|
||||
});
|
||||
updateTransferList();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -201,6 +239,7 @@ initializeWindows = function() {
|
|||
}
|
||||
}).send();
|
||||
});
|
||||
updateTransferList();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -216,6 +255,7 @@ initializeWindows = function() {
|
|||
}
|
||||
}).send();
|
||||
});
|
||||
updateTransferList();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -248,6 +288,7 @@ initializeWindows = function() {
|
|||
}
|
||||
}).send();
|
||||
});
|
||||
updateTransferList();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -276,6 +317,7 @@ initializeWindows = function() {
|
|||
hashes: h.join("|")
|
||||
}
|
||||
}).send();
|
||||
updateTransferList();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,11 +52,17 @@
|
|||
ForceRecheck : function (element, ref) {
|
||||
recheckFN();
|
||||
},
|
||||
UploadLimit : function (element, red) {
|
||||
UploadLimit : function (element, ref) {
|
||||
uploadLimitFN();
|
||||
},
|
||||
DownloadLimit : function (element, red) {
|
||||
DownloadLimit : function (element, ref) {
|
||||
downloadLimitFN();
|
||||
},
|
||||
SequentialDownload : function (element, ref) {
|
||||
toggleSequentialDownloadFN();
|
||||
},
|
||||
FirstLastPiecePrio : function (element, ref) {
|
||||
toggleFirstLastPiecePrioFN();
|
||||
}
|
||||
},
|
||||
offsets : {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue