From 329b7541970a04e57807dd6f062ce25391ef3f37 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Wed, 14 May 2014 02:09:45 +0400 Subject: [PATCH] cache torrent_status --- src/properties/propertieswidget.cpp | 37 ++--- src/qtlibtorrent/qbtsession.cpp | 24 ++- src/qtlibtorrent/qbtsession.h | 4 +- src/qtlibtorrent/qtorrenthandle.cpp | 181 +++++++---------------- src/qtlibtorrent/qtorrenthandle.h | 33 +---- src/qtlibtorrent/torrentmodel.cpp | 65 ++++---- src/qtlibtorrent/torrentmodel.h | 2 + src/qtlibtorrent/torrentspeedmonitor.cpp | 16 +- src/qtlibtorrent/torrentspeedmonitor.h | 2 +- src/webui/btjson.cpp | 64 ++++---- 10 files changed, 176 insertions(+), 252 deletions(-) diff --git a/src/properties/propertieswidget.cpp b/src/properties/propertieswidget.cpp index 95fd5fd1f..3552d52c1 100644 --- a/src/properties/propertieswidget.cpp +++ b/src/properties/propertieswidget.cpp @@ -316,28 +316,31 @@ void PropertiesWidget::loadDynamicData() { // Refresh only if the torrent handle is valid and if visible if (!h.is_valid() || main_window->getCurrentTabWidget() != transferList || state != VISIBLE) return; try { + libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters + | torrent_handle::query_distributed_copies + | torrent_handle::query_pieces); // Transfer infos if (stackedProperties->currentIndex() == PropTabBar::MAIN_TAB) { - wasted->setText(misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes())); - upTotal->setText(misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")"); - dlTotal->setText(misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")"); + wasted->setText(misc::friendlyUnit(status.total_failed_bytes+status.total_redundant_bytes)); + upTotal->setText(misc::friendlyUnit(status.all_time_upload) + " ("+misc::friendlyUnit(status.total_payload_upload)+" "+tr("this session")+")"); + dlTotal->setText(misc::friendlyUnit(status.all_time_download) + " ("+misc::friendlyUnit(status.total_payload_download)+" "+tr("this session")+")"); lbl_uplimit->setText(h.upload_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)")); lbl_dllimit->setText(h.download_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)")); - QString elapsed_txt = misc::userFriendlyDuration(h.active_time()); - if (h.is_seed()) { - elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")"; + QString elapsed_txt = misc::userFriendlyDuration(status.active_time); + if (h.is_seed(status)) { + elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(status.seeding_time))+")"; } lbl_elapsed->setText(elapsed_txt); - if (h.connections_limit() > 0) - lbl_connections->setText(QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")"); + if (status.connections_limit > 0) + lbl_connections->setText(QString::number(status.num_connections)+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(status.connections_limit))+")"); else - lbl_connections->setText(QString::number(h.num_connections())); + lbl_connections->setText(QString::number(status.num_connections)); // Update next announce time - reannounce_lbl->setText(h.next_announce()); + reannounce_lbl->setText(misc::userFriendlyDuration(status.next_announce.total_seconds())); // Update ratio info - const qreal ratio = QBtSession::instance()->getRealRatio(h); + const qreal ratio = QBtSession::instance()->getRealRatio(status); shareRatio->setText(ratio > QBtSession::MAX_RATIO ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 2)); - if (!h.is_seed() && h.has_metadata()) { + if (!h.is_seed(status) && status.has_metadata) { showPiecesDownloaded(true); // Downloaded pieces #if LIBTORRENT_VERSION_NUM < 10000 @@ -346,19 +349,19 @@ void PropertiesWidget::loadDynamicData() { bitfield bf(h.torrent_file()->num_pieces(), 0); #endif h.downloading_pieces(bf); - downloaded_pieces->setProgress(h.pieces(), bf); + downloaded_pieces->setProgress(status.pieces, bf); // Pieces availability - if (!h.is_paused() && !h.is_queued() && !h.is_checking()) { + if (!h.is_paused(status) && !h.is_queued(status) && !h.is_checking(status)) { showPiecesAvailability(true); std::vector avail; h.piece_availability(avail); pieces_availability->setAvailability(avail); - avail_average_lbl->setText(misc::accurateDoubleToString(h.distributed_copies(), 3)); + avail_average_lbl->setText(misc::accurateDoubleToString(status.distributed_copies, 3)); } else { showPiecesAvailability(false); } // Progress - qreal progress = h.progress()*100.; + qreal progress = h.progress(status)*100.; progress_lbl->setText(misc::accurateDoubleToString(progress, 1)+"%"); } else { showPiecesAvailability(false); @@ -378,7 +381,7 @@ void PropertiesWidget::loadDynamicData() { } if (stackedProperties->currentIndex() == PropTabBar::FILES_TAB) { // Files progress - if (h.is_valid() && h.has_metadata()) { + if (h.is_valid() && status.has_metadata) { qDebug("Updating priorities in files tab"); filesList->setUpdatesEnabled(false); std::vector fp; diff --git a/src/qtlibtorrent/qbtsession.cpp b/src/qtlibtorrent/qbtsession.cpp index eeaa1ab31..0d00f228b 100755 --- a/src/qtlibtorrent/qbtsession.cpp +++ b/src/qtlibtorrent/qbtsession.cpp @@ -220,7 +220,7 @@ void QBtSession::processBigRatios() { if (!h.is_valid()) continue; if (h.is_seed()) { const QString hash = h.hash(); - const qreal ratio = getRealRatio(h); + const qreal ratio = getRealRatio(h.status(torrent_handle::query_accurate_download_counters)); qreal ratio_limit = TorrentPersistentData::getRatioLimit(hash); if (ratio_limit == TorrentPersistentData::USE_GLOBAL_RATIO) ratio_limit = global_ratio_limit; @@ -1556,14 +1556,11 @@ bool QBtSession::enableDHT(bool b) { return true; } -qreal QBtSession::getRealRatio(QTorrentHandle h) const { - if (!h.is_valid()) { - return 0.; - } +qreal QBtSession::getRealRatio(const libtorrent::torrent_status &status) const { + libtorrent::size_type all_time_upload = status.all_time_upload; + libtorrent::size_type all_time_download = status.all_time_download; + libtorrent::size_type total_done = status.total_done; - libtorrent::size_type all_time_upload = h.all_time_upload(); - libtorrent::size_type all_time_download = h.all_time_download(); - libtorrent::size_type total_done = h.total_done(); if (all_time_download < total_done) { // We have more data on disk than we downloaded // either because the user imported the file @@ -1576,7 +1573,7 @@ qreal QBtSession::getRealRatio(QTorrentHandle h) const { if (all_time_download == 0) { if (all_time_upload == 0) - return 0; + return 0.0; return MAX_RATIO+1; } @@ -2106,11 +2103,12 @@ void QBtSession::autoRunExternalProgram(const QTorrentHandle &h) { } void QBtSession::sendNotificationEmail(const QTorrentHandle &h) { + libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters); // Prepare mail content QString content = tr("Torrent name: %1").arg(h.name()) + "\n"; - content += tr("Torrent size: %1").arg(misc::friendlyUnit(h.actual_size())) + "\n"; + content += tr("Torrent size: %1").arg(misc::friendlyUnit(status.total_wanted)) + "\n"; content += tr("Save path: %1").arg(TorrentPersistentData::getSavePath(h.hash())) + "\n\n"; - content += tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds").arg(misc::userFriendlyDuration(h.active_time())) + "\n\n\n"; + content += tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds").arg(misc::userFriendlyDuration(status.active_time)) + "\n\n\n"; content += tr("Thank you for using qBittorrent.") + "\n"; // Send the notification email Smtp *sender = new Smtp(this); @@ -2803,9 +2801,9 @@ void QBtSession::drop() } } -qlonglong QBtSession::getETA(const QString &hash) const +qlonglong QBtSession::getETA(const QString &hash, const libtorrent::torrent_status &status) const { - return m_speedMonitor->getETA(hash); + return m_speedMonitor->getETA(hash, status); } quint64 QBtSession::getAlltimeDL() const { diff --git a/src/qtlibtorrent/qbtsession.h b/src/qtlibtorrent/qbtsession.h index f69d8d0d0..3a35b30e0 100755 --- a/src/qtlibtorrent/qbtsession.h +++ b/src/qtlibtorrent/qbtsession.h @@ -92,7 +92,7 @@ public: qreal getPayloadUploadRate() const; libtorrent::session_status getSessionStatus() const; int getListenPort() const; - qreal getRealRatio(QTorrentHandle h) const; + qreal getRealRatio(const libtorrent::torrent_status &status) const; QHash getTrackersInfo(const QString &hash) const; bool hasActiveTorrents() const; bool hasDownloadingTorrents() const; @@ -121,7 +121,7 @@ public slots: void startUpTorrents(); void recheckTorrent(const QString &hash); void useAlternativeSpeedsLimit(bool alternative); - qlonglong getETA(const QString& hash) const; + qlonglong getETA(const QString& hash, const libtorrent::torrent_status &status) const; /* Needed by Web UI */ void pauseAllTorrents(); void pauseTorrent(const QString &hash); diff --git a/src/qtlibtorrent/qtorrenthandle.cpp b/src/qtlibtorrent/qtorrenthandle.cpp index e6987a1f3..a44eae05e 100644 --- a/src/qtlibtorrent/qtorrenthandle.cpp +++ b/src/qtlibtorrent/qtorrenthandle.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "fs_utils.h" #include "misc.h" @@ -87,7 +88,7 @@ QString QTorrentHandle::name() const { #if LIBTORRENT_VERSION_NUM < 10000 name = misc::toQStringU(torrent_handle::name()); #else - name = misc::toQStringU(torrent_handle::status(torrent_handle::query_name).name); + name = misc::toQStringU(status(query_name).name); #endif } return name; @@ -102,41 +103,16 @@ QString QTorrentHandle::creation_date() const { return t ? misc::toQString(*t) : ""; } -QString QTorrentHandle::next_announce() const { - return misc::userFriendlyDuration(torrent_handle::status(0x0).next_announce.total_seconds()); -} - -qlonglong QTorrentHandle::next_announce_s() const { - return torrent_handle::status(0x0).next_announce.total_seconds(); -} - -float QTorrentHandle::progress() const { - torrent_status st = torrent_handle::status(query_accurate_download_counters); - if (!st.total_wanted) - return 0.; - if (st.total_wanted_done == st.total_wanted) - return 1.; - float progress = (float) st.total_wanted_done / (float) st.total_wanted; - Q_ASSERT(progress >= 0. && progress <= 1.); - return progress; -} - -bitfield QTorrentHandle::pieces() const { - return torrent_handle::status(torrent_handle::query_pieces).pieces; -} - QString QTorrentHandle::current_tracker() const { - return misc::toQString(torrent_handle::status(0x0).current_tracker); + return misc::toQString(status(0x0).current_tracker); } bool QTorrentHandle::is_paused() const { - torrent_status st = torrent_handle::status(0x0); - return st.paused && !st.auto_managed; + return is_paused(status(0x0)); } bool QTorrentHandle::is_queued() const { - torrent_status st = torrent_handle::status(0x0); - return st.paused && st.auto_managed; + return is_queued(status(0x0)); } size_type QTorrentHandle::total_size() const { @@ -189,38 +165,6 @@ bool QTorrentHandle::first_last_piece_first() const { && (torrent_handle::piece_priority(extremities.second) == 7); } -size_type QTorrentHandle::total_wanted_done() const { - return torrent_handle::status(query_accurate_download_counters).total_wanted_done; -} - -size_type QTorrentHandle::total_wanted() const { - return torrent_handle::status(0x0).total_wanted; -} - -qreal QTorrentHandle::download_payload_rate() const { - return torrent_handle::status(0x0).download_payload_rate; -} - -qreal QTorrentHandle::upload_payload_rate() const { - return torrent_handle::status(0x0).upload_payload_rate; -} - -int QTorrentHandle::num_peers() const { - return torrent_handle::status(0x0).num_peers; -} - -int QTorrentHandle::num_seeds() const { - return torrent_handle::status(0x0).num_seeds; -} - -int QTorrentHandle::num_complete() const { - return torrent_handle::status(0x0).num_complete; -} - -int QTorrentHandle::num_incomplete() const { - return torrent_handle::status(0x0).num_incomplete; -} - QString QTorrentHandle::save_path() const { #if LIBTORRENT_VERSION_NUM < 10000 return fsutils::fromNativePath(misc::toQStringU(torrent_handle::save_path())); @@ -260,7 +204,7 @@ QStringList QTorrentHandle::url_seeds() const { // get the size of the torrent without the filtered files size_type QTorrentHandle::actual_size() const { - return torrent_handle::status(query_accurate_download_counters).total_wanted; + return status(query_accurate_download_counters).total_wanted; } bool QTorrentHandle::has_filtered_pieces() const { @@ -317,7 +261,7 @@ QString QTorrentHandle::orig_filepath_at(unsigned int index) const { } torrent_status::state_t QTorrentHandle::state() const { - return torrent_handle::status(0x0).state; + return status(0x0).state; } QString QTorrentHandle::creator() const { @@ -336,37 +280,8 @@ QString QTorrentHandle::comment() const { #endif } -size_type QTorrentHandle::total_failed_bytes() const { - return torrent_handle::status(0x0).total_failed_bytes; -} - -size_type QTorrentHandle::total_redundant_bytes() const { - return torrent_handle::status(0x0).total_redundant_bytes; -} - bool QTorrentHandle::is_checking() const { - torrent_status st = torrent_handle::status(0x0); - return st.state == torrent_status::checking_files || st.state == torrent_status::checking_resume_data; -} - -size_type QTorrentHandle::total_done() const { - return torrent_handle::status(query_accurate_download_counters).total_done; -} - -size_type QTorrentHandle::all_time_download() const { - return torrent_handle::status(0x0).all_time_download; -} - -size_type QTorrentHandle::all_time_upload() const { - return torrent_handle::status(0x0).all_time_upload; -} - -size_type QTorrentHandle::total_payload_download() const { - return torrent_handle::status(0x0).total_payload_download; -} - -size_type QTorrentHandle::total_payload_upload() const { - return torrent_handle::status(0x0).total_payload_upload; + return is_checking(status(0x0)); } // Return a list of absolute paths corresponding @@ -408,44 +323,17 @@ int QTorrentHandle::queue_position() const { return torrent_handle::queue_position()+1; } -int QTorrentHandle::num_uploads() const { - return torrent_handle::status(0x0).num_uploads; -} - 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 //return (progress() == 1.); // This looks safe - torrent_status::state_t st = state(); - return (st == torrent_status::finished || st == torrent_status::seeding); -} - -bool QTorrentHandle::is_auto_managed() const { - torrent_status status = torrent_handle::status(0x0); - return status.auto_managed; + return is_seed(status(0x0)); } bool QTorrentHandle::is_sequential_download() const { - torrent_status status = torrent_handle::status(0x0); - return status.sequential_download; -} - -qlonglong QTorrentHandle::active_time() const { - return torrent_handle::status(0x0).active_time; -} - -qlonglong QTorrentHandle::seeding_time() const { - return torrent_handle::status(0x0).seeding_time; -} - -int QTorrentHandle::num_connections() const { - return torrent_handle::status(0x0).num_connections; -} - -int QTorrentHandle::connections_limit() const { - return torrent_handle::status(0x0).connections_limit; + return status(0x0).sequential_download; } bool QTorrentHandle::priv() const { @@ -482,12 +370,11 @@ QString QTorrentHandle::root_path() const } bool QTorrentHandle::has_error() const { - torrent_status st = torrent_handle::status(0x0); - return st.paused && !st.error.empty(); + return has_error(status(0x0)); } QString QTorrentHandle::error() const { - return misc::toQString(torrent_handle::status(0x0).error); + return misc::toQString(status(0x0).error); } void QTorrentHandle::downloading_pieces(bitfield &bf) const { @@ -503,11 +390,7 @@ void QTorrentHandle::downloading_pieces(bitfield &bf) const { } bool QTorrentHandle::has_metadata() const { - return torrent_handle::status(0x0).has_metadata; -} - -float QTorrentHandle::distributed_copies() const { - return torrent_handle::status(query_distributed_copies).distributed_copies; + return status(0x0).has_metadata; } void QTorrentHandle::file_progress(std::vector& fp) const { @@ -732,3 +615,41 @@ void QTorrentHandle::rename_file(int index, const QString& name) 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) +{ + return status.paused && !status.auto_managed; +} + +bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status) +{ + return status.paused && status.auto_managed; +} + +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) +{ + return status.state == torrent_status::checking_files + || status.state == torrent_status::checking_resume_data; +} + +bool QTorrentHandle::has_error(const libtorrent::torrent_status &status) +{ + return status.paused && !status.error.empty(); +} + +float QTorrentHandle::progress(const libtorrent::torrent_status &status) +{ + if (!status.total_wanted) + return 0.; + if (status.total_wanted_done == status.total_wanted) + return 1.; + float progress = (float) status.total_wanted_done / (float) status.total_wanted; + Q_ASSERT(progress >= 0.f && progress <= 1.f); + return progress; +} diff --git a/src/qtlibtorrent/qtorrenthandle.h b/src/qtlibtorrent/qtorrenthandle.h index a32453f48..9c79e93e2 100644 --- a/src/qtlibtorrent/qtorrenthandle.h +++ b/src/qtlibtorrent/qtorrenthandle.h @@ -59,24 +59,12 @@ public: // QString hash() const; QString name() const; - float progress() const; - libtorrent::bitfield pieces() const; QString current_tracker() const; bool is_paused() const; bool has_filtered_pieces() const; libtorrent::size_type total_size() const; libtorrent::size_type piece_length() const; int num_pieces() const; - libtorrent::size_type total_wanted_done() const; - libtorrent::size_type total_wanted() const; - qreal download_payload_rate() const; - qreal upload_payload_rate() const; - int num_connections() const; - int connections_limit() const; - int num_peers() const; - int num_seeds() const; - int num_complete() const; - int num_incomplete() const; QString save_path() const; QString save_path_parsed() const; QStringList url_seeds() const; @@ -91,26 +79,13 @@ public: libtorrent::torrent_status::state_t state() const; QString creator() const; QString comment() const; - libtorrent::size_type total_failed_bytes() const; - libtorrent::size_type total_redundant_bytes() const; - libtorrent::size_type total_payload_download() const; - libtorrent::size_type total_payload_upload() const; - libtorrent::size_type all_time_upload() const; - libtorrent::size_type all_time_download() const; - libtorrent::size_type total_done() const; QStringList absolute_files_path() const; QStringList absolute_files_path_uneeded() const; bool has_missing_files() const; - int num_uploads() const; bool is_seed() const; bool is_checking() const; - bool is_auto_managed() const; bool is_sequential_download() const; - qlonglong active_time() const; - qlonglong seeding_time() const; QString creation_date() const; - QString next_announce() const; - qlonglong next_announce_s() const; bool priv() const; bool first_last_piece_first() const; QString root_path() const; @@ -119,7 +94,6 @@ public: QString error() const; void downloading_pieces(libtorrent::bitfield& bf) const; bool has_metadata() const; - float distributed_copies() const; void file_progress(std::vector& fp) const; // @@ -142,6 +116,13 @@ public: // bool operator ==(const QTorrentHandle& new_h) const; + static bool is_paused(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_checking(const libtorrent::torrent_status &status); + static bool has_error(const libtorrent::torrent_status &status); + static float progress(const libtorrent::torrent_status &status); + private: void prioritize_first_last_piece(int file_index, bool b) const; diff --git a/src/qtlibtorrent/torrentmodel.cpp b/src/qtlibtorrent/torrentmodel.cpp index 577e289c3..8140f4833 100644 --- a/src/qtlibtorrent/torrentmodel.cpp +++ b/src/qtlibtorrent/torrentmodel.cpp @@ -90,6 +90,7 @@ namespace TorrentModelItem::TorrentModelItem(const QTorrentHandle &h) : m_torrent(h) + , m_lastStatus(h.status(torrent_handle::query_accurate_download_counters)) , m_addedTime(TorrentPersistentData::getAddedDate(h.hash())) , m_seedTime(TorrentPersistentData::getSeedDate(h.hash())) , m_label(TorrentPersistentData::getLabel(h.hash())) @@ -100,26 +101,33 @@ TorrentModelItem::TorrentModelItem(const QTorrentHandle &h) m_name = h.name(); } +void TorrentModelItem::refreshStatus() +{ + try { + m_lastStatus = m_torrent.status(); + } catch(invalid_handle&) {} +} + TorrentModelItem::State TorrentModelItem::state() const { try { // Pause or Queued - if (m_torrent.is_paused()) { + if (m_torrent.is_paused(m_lastStatus)) { m_icon = get_paused_icon(); m_fgColor = QColor("red"); - return m_torrent.is_seed() ? STATE_PAUSED_UP : STATE_PAUSED_DL; + return m_torrent.is_seed(m_lastStatus) ? STATE_PAUSED_UP : STATE_PAUSED_DL; } - if (m_torrent.is_queued()) { - if (m_torrent.state() != torrent_status::queued_for_checking - && m_torrent.state() != torrent_status::checking_resume_data - && m_torrent.state() != torrent_status::checking_files) { + if (m_torrent.is_queued(m_lastStatus)) { + if (m_lastStatus.state != torrent_status::queued_for_checking + && m_lastStatus.state != torrent_status::checking_resume_data + && m_lastStatus.state != torrent_status::checking_files) { m_icon = get_queued_icon(); m_fgColor = QColor("grey"); - return m_torrent.is_seed() ? STATE_QUEUED_UP : STATE_QUEUED_DL; + return m_torrent.is_seed(m_lastStatus) ? STATE_QUEUED_UP : STATE_QUEUED_DL; } } // Other states - switch(m_torrent.state()) { + switch(m_lastStatus.state) { case torrent_status::allocating: m_icon = get_stalled_downloading_icon(); m_fgColor = QColor("grey"); @@ -129,7 +137,7 @@ TorrentModelItem::State TorrentModelItem::state() const m_fgColor = QColor("green"); return STATE_DOWNLOADING_META; case torrent_status::downloading: { - if (m_torrent.download_payload_rate() > 0) { + if (m_lastStatus.download_payload_rate > 0) { m_icon = get_downloading_icon(); m_fgColor = QColor("green"); return STATE_DOWNLOADING; @@ -141,7 +149,7 @@ TorrentModelItem::State TorrentModelItem::state() const } case torrent_status::finished: case torrent_status::seeding: - if (m_torrent.upload_payload_rate() > 0) { + if (m_lastStatus.upload_payload_rate > 0) { m_icon = get_uploading_icon(); m_fgColor = QColor("orange"); return STATE_SEEDING; @@ -161,7 +169,7 @@ TorrentModelItem::State TorrentModelItem::state() const case torrent_status::checking_files: m_icon = get_checking_icon(); m_fgColor = QColor("grey"); - return m_torrent.is_seed() ? STATE_CHECKING_UP : STATE_CHECKING_DL; + return m_torrent.is_seed(m_lastStatus) ? STATE_CHECKING_UP : STATE_CHECKING_DL; default: m_icon = get_error_icon(); m_fgColor = QColor("red"); @@ -224,28 +232,28 @@ QVariant TorrentModelItem::data(int column, int role) const return pos; } case TR_SIZE: - return m_torrent.has_metadata() ? static_cast(m_torrent.actual_size()) : -1; + return m_lastStatus.has_metadata ? static_cast(m_lastStatus.total_wanted) : -1; case TR_PROGRESS: - return m_torrent.progress(); + return m_torrent.progress(m_lastStatus); case TR_STATUS: return state(); case TR_SEEDS: { - return (role == Qt::DisplayRole) ? m_torrent.num_seeds() : m_torrent.num_complete(); + return (role == Qt::DisplayRole) ? m_lastStatus.num_seeds : m_lastStatus.num_complete; } case TR_PEERS: { - return (role == Qt::DisplayRole) ? (m_torrent.num_peers()-m_torrent.num_seeds()) : m_torrent.num_incomplete(); + return (role == Qt::DisplayRole) ? (m_lastStatus.num_peers-m_lastStatus.num_seeds) : m_lastStatus.num_incomplete; } case TR_DLSPEED: - return m_torrent.download_payload_rate(); + return m_lastStatus.download_payload_rate; case TR_UPSPEED: - return m_torrent.upload_payload_rate(); + return m_lastStatus.upload_payload_rate; case TR_ETA: { // XXX: Is this correct? - if (m_torrent.is_paused() || m_torrent.is_queued()) return MAX_ETA; - return QBtSession::instance()->getETA(m_hash); + if (m_torrent.is_paused(m_lastStatus) || m_torrent.is_queued(m_lastStatus)) return MAX_ETA; + return QBtSession::instance()->getETA(m_hash, m_lastStatus); } case TR_RATIO: - return QBtSession::instance()->getRealRatio(m_torrent); + return QBtSession::instance()->getRealRatio(m_lastStatus); case TR_LABEL: return m_label; case TR_ADD_DATE: @@ -253,19 +261,19 @@ QVariant TorrentModelItem::data(int column, int role) const case TR_SEED_DATE: return m_seedTime; case TR_TRACKER: - return m_torrent.current_tracker(); + return misc::toQString(m_lastStatus.current_tracker); case TR_DLLIMIT: return m_torrent.download_limit(); case TR_UPLIMIT: return m_torrent.upload_limit(); case TR_AMOUNT_DOWNLOADED: - return static_cast(m_torrent.all_time_download()); + return static_cast(m_lastStatus.all_time_download); case TR_AMOUNT_UPLOADED: - return static_cast(m_torrent.all_time_upload()); + return static_cast(m_lastStatus.all_time_upload); case TR_AMOUNT_LEFT: - return static_cast(m_torrent.total_wanted() - m_torrent.total_wanted_done()); + return static_cast(m_lastStatus.total_wanted - m_lastStatus.total_wanted_done); case TR_TIME_ELAPSED: - return (role == Qt::DisplayRole) ? m_torrent.active_time() : m_torrent.seeding_time(); + return (role == Qt::DisplayRole) ? m_lastStatus.active_time : m_lastStatus.seeding_time; case TR_SAVE_PATH: return fsutils::toNativePath(m_torrent.save_path_parsed()); default: @@ -464,6 +472,13 @@ void TorrentModel::setRefreshInterval(int refreshInterval) void TorrentModel::forceModelRefresh() { + QList::const_iterator it = m_torrents.constBegin(); + QList::const_iterator itend = m_torrents.constEnd(); + for ( ; it != itend; ++it) { + TorrentModelItem* item = *it; + item->refreshStatus(); + } + emit dataChanged(index(0, 0), index(rowCount()-1, columnCount()-1)); } diff --git a/src/qtlibtorrent/torrentmodel.h b/src/qtlibtorrent/torrentmodel.h index 94e9dcae9..ce1648801 100644 --- a/src/qtlibtorrent/torrentmodel.h +++ b/src/qtlibtorrent/torrentmodel.h @@ -53,6 +53,7 @@ public: public: TorrentModelItem(const QTorrentHandle& h); + void refreshStatus(); inline int columnCount() const { return NB_COLUMNS; } QVariant data(int column, int role = Qt::DisplayRole) const; bool setData(int column, const QVariant &value, int role = Qt::DisplayRole); @@ -66,6 +67,7 @@ private: private: QTorrentHandle m_torrent; + libtorrent::torrent_status m_lastStatus; QDateTime m_addedTime; QDateTime m_seedTime; QString m_label; diff --git a/src/qtlibtorrent/torrentspeedmonitor.cpp b/src/qtlibtorrent/torrentspeedmonitor.cpp index 678a63c7b..623e47b7e 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.cpp +++ b/src/qtlibtorrent/torrentspeedmonitor.cpp @@ -130,16 +130,16 @@ void TorrentSpeedMonitor::removeSamples(const QTorrentHandle& h) { } catch(invalid_handle&) {} } -qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const +qlonglong TorrentSpeedMonitor::getETA(const QString &hash, const libtorrent::torrent_status &status) const { QMutexLocker locker(&m_mutex); - QTorrentHandle h = m_session->getTorrentHandle(hash); - if (h.is_paused() || !m_samples.contains(hash)) + + if (QTorrentHandle::is_paused(status) || !m_samples.contains(hash)) return MAX_ETA; const Sample speed_average = m_samples[hash].average(); - if (h.is_seed()) { + if (QTorrentHandle::is_seed(status)) { if (!speed_average.upload) return MAX_ETA; @@ -148,17 +148,17 @@ qlonglong TorrentSpeedMonitor::getETA(const QString &hash) const if (max_ratio < 0) return MAX_ETA; - libtorrent::size_type realDL = h.all_time_download(); + libtorrent::size_type realDL = status.all_time_download; if (realDL <= 0) - realDL = h.total_wanted(); + realDL = status.total_wanted; - return (realDL * max_ratio - h.all_time_upload()) / speed_average.upload; + return (realDL * max_ratio - status.all_time_upload) / speed_average.upload; } if (!speed_average.download) return MAX_ETA; - return (h.total_wanted() - h.total_wanted_done()) / speed_average.download; + return (status.total_wanted - status.total_wanted_done) / speed_average.download; } quint64 TorrentSpeedMonitor::getAlltimeDL() const { diff --git a/src/qtlibtorrent/torrentspeedmonitor.h b/src/qtlibtorrent/torrentspeedmonitor.h index 0d71d64f6..3707e7740 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.h +++ b/src/qtlibtorrent/torrentspeedmonitor.h @@ -48,7 +48,7 @@ class TorrentSpeedMonitor : public QThread public: explicit TorrentSpeedMonitor(QBtSession* session); ~TorrentSpeedMonitor(); - qlonglong getETA(const QString &hash) const; + qlonglong getETA(const QString &hash, const libtorrent::torrent_status &status) const; quint64 getAlltimeDL() const; quint64 getAlltimeUL() const; diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index b8f87b989..42cbd0d34 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -124,53 +124,55 @@ static const char KEY_TRANSFER_UPSPEED[] = "up_info"; static JsonDict toJson(const QTorrentHandle& h) { + libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters); + JsonDict ret; ret.add(KEY_TORRENT_HASH, h.hash()); ret.add(KEY_TORRENT_NAME, h.name()); - ret.add(KEY_TORRENT_SIZE, misc::friendlyUnit(h.actual_size())); // FIXME: Should pass as Number, not formatted String (for sorting). - ret.add(KEY_TORRENT_PROGRESS, (double)h.progress()); - ret.add(KEY_TORRENT_DLSPEED, misc::friendlyUnit(h.download_payload_rate(), true)); // FIXME: Should be passed as a Number - ret.add(KEY_TORRENT_UPSPEED, misc::friendlyUnit(h.upload_payload_rate(), true)); // FIXME: Should be passed as a Number + ret.add(KEY_TORRENT_SIZE, misc::friendlyUnit(status.total_wanted)); // FIXME: Should pass as Number, not formatted String (for sorting). + ret.add(KEY_TORRENT_PROGRESS, (double)h.progress(status)); + ret.add(KEY_TORRENT_DLSPEED, misc::friendlyUnit(status.download_payload_rate, true)); // FIXME: Should be passed as a Number + ret.add(KEY_TORRENT_UPSPEED, misc::friendlyUnit(status.upload_payload_rate, true)); // FIXME: Should be passed as a Number if (QBtSession::instance()->isQueueingEnabled() && h.queue_position() >= 0) ret.add(KEY_TORRENT_PRIORITY, QString::number(h.queue_position())); else ret.add(KEY_TORRENT_PRIORITY, "*"); - QString seeds = QString::number(h.num_seeds()); - if (h.num_complete() > 0) - seeds += " ("+QString::number(h.num_complete())+")"; + QString seeds = QString::number(status.num_seeds); + if (status.num_complete > 0) + seeds += " ("+QString::number(status.num_complete)+")"; ret.add(KEY_TORRENT_SEEDS, seeds); - QString leechs = QString::number(h.num_peers() - h.num_seeds()); - if (h.num_incomplete() > 0) - leechs += " ("+QString::number(h.num_incomplete())+")"; + QString leechs = QString::number(status.num_peers - status.num_seeds); + if (status.num_incomplete > 0) + leechs += " ("+QString::number(status.num_incomplete)+")"; ret.add(KEY_TORRENT_LEECHS, leechs); - const qreal ratio = QBtSession::instance()->getRealRatio(h); + const qreal ratio = QBtSession::instance()->getRealRatio(status); ret.add(KEY_TORRENT_RATIO, (ratio > 100.) ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1)); QString eta; QString state; - if (h.is_paused()) { - if (h.has_error()) + if (h.is_paused(status)) { + if (h.has_error(status)) state = "error"; else - state = h.is_seed() ? "pausedUP" : "pausedDL"; + state = h.is_seed(status) ? "pausedUP" : "pausedDL"; } else { - if (QBtSession::instance()->isQueueingEnabled() && h.is_queued()) - state = h.is_seed() ? "queuedUP" : "queuedDL"; + if (QBtSession::instance()->isQueueingEnabled() && h.is_queued(status)) + state = h.is_seed(status) ? "queuedUP" : "queuedDL"; else { - switch (h.state()) { + switch (status.state) { case torrent_status::finished: case torrent_status::seeding: - state = h.upload_payload_rate() > 0 ? "uploading" : "stalledUP"; + state = status.upload_payload_rate > 0 ? "uploading" : "stalledUP"; break; case torrent_status::allocating: case torrent_status::checking_files: case torrent_status::queued_for_checking: case torrent_status::checking_resume_data: - state = h.is_seed() ? "checkingUP" : "checkingDL"; + state = h.is_seed(status) ? "checkingUP" : "checkingDL"; break; case torrent_status::downloading: case torrent_status::downloading_metadata: - state = h.download_payload_rate() > 0 ? "downloading" : "stalledDL"; - eta = misc::userFriendlyDuration(QBtSession::instance()->getETA(h.hash())); + state = status.download_payload_rate > 0 ? "downloading" : "stalledDL"; + eta = misc::userFriendlyDuration(QBtSession::instance()->getETA(h.hash(), status)); break; default: qWarning("Unrecognized torrent status, should not happen!!! status was %d", h.state()); @@ -284,7 +286,9 @@ QString btjson::getPropertiesForTorrent(const QString& hash) try { QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); - if (!h.has_metadata()) + libtorrent::torrent_status status = h.status(torrent_handle::query_accurate_download_counters); + + if (!status.has_metadata) return QString(); // Save path @@ -295,17 +299,17 @@ QString btjson::getPropertiesForTorrent(const QString& hash) data.add(KEY_PROP_CREATION_DATE, h.creation_date()); data.add(KEY_PROP_PIECE_SIZE, misc::friendlyUnit(h.piece_length())); data.add(KEY_PROP_COMMENT, h.comment()); - data.add(KEY_PROP_WASTED, misc::friendlyUnit(h.total_failed_bytes() + h.total_redundant_bytes())); - data.add(KEY_PROP_UPLOADED, QString(misc::friendlyUnit(h.all_time_upload()) + " (" + misc::friendlyUnit(h.total_payload_upload()) + " " + tr("this session") + ")")); - data.add(KEY_PROP_DOWNLOADED, QString(misc::friendlyUnit(h.all_time_download()) + " (" + misc::friendlyUnit(h.total_payload_download()) + " " + tr("this session") + ")")); + data.add(KEY_PROP_WASTED, misc::friendlyUnit(status.total_failed_bytes + status.total_redundant_bytes)); + data.add(KEY_PROP_UPLOADED, QString(misc::friendlyUnit(status.all_time_upload) + " (" + misc::friendlyUnit(status.total_payload_upload) + " " + tr("this session") + ")")); + data.add(KEY_PROP_DOWNLOADED, QString(misc::friendlyUnit(status.all_time_download) + " (" + misc::friendlyUnit(status.total_payload_download) + " " + tr("this session") + ")")); data.add(KEY_PROP_UP_LIMIT, h.upload_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.upload_limit(), true)); data.add(KEY_PROP_DL_LIMIT, h.download_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.download_limit(), true)); - QString elapsed_txt = misc::userFriendlyDuration(h.active_time()); - if (h.is_seed()) - elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")"; + QString elapsed_txt = misc::userFriendlyDuration(status.active_time); + if (h.is_seed(status)) + elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(status.seeding_time))+")"; data.add(KEY_PROP_TIME_ELAPSED, elapsed_txt); - data.add(KEY_PROP_CONNECT_COUNT, QString(QString::number(h.num_connections()) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit())) + ")")); - const qreal ratio = QBtSession::instance()->getRealRatio(h); + data.add(KEY_PROP_CONNECT_COUNT, QString(QString::number(status.num_connections) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(status.connections_limit)) + ")")); + const qreal ratio = QBtSession::instance()->getRealRatio(status); data.add(KEY_PROP_RATIO, ratio > 100. ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1)); } catch(const std::exception& e) { qWarning() << Q_FUNC_INFO << "Invalid torrent: " << e.what();