mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-17 15:42:30 +00:00
Let the download list own its downloads through a shared pointer.
A multicall could then dispatch commands on an erased download.
This commit is contained in:
+23
-5
@@ -51,7 +51,7 @@ apply_on_ratio(const torrent::Object& rawArgs) {
|
||||
!(max_ratio > 0 && total_upload * 100 > total_done * max_ratio))
|
||||
continue;
|
||||
|
||||
downloads.push_back(*itr);
|
||||
downloads.push_back(itr->get());
|
||||
}
|
||||
|
||||
auto ratio_command = "group." + group_name + ".ratio.command";
|
||||
@@ -173,7 +173,7 @@ apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
|
||||
|
||||
torrent::FileList::cache_list cache;
|
||||
|
||||
for (auto download : *control->core()->download_list()) {
|
||||
for (const auto& download : *control->core()->download_list()) {
|
||||
if (!download->is_downloading())
|
||||
continue;
|
||||
if (download->priority() >= skip_priority)
|
||||
@@ -240,15 +240,25 @@ d_multicall(const torrent::Object::list_type& args) {
|
||||
|
||||
// Add some pre-parsing of the commands, so we don't spend time
|
||||
// parsing and searching command map for every single call.
|
||||
std::vector<core::Download*> dlist((*view_itr)->begin_visible(), (*view_itr)->end_visible());
|
||||
// Hold a reference to each download so a command that erases one does not
|
||||
// leave the rest of the loop dispatching on freed memory.
|
||||
core::View::base_type dlist((*view_itr)->begin_visible(), (*view_itr)->end_visible());
|
||||
|
||||
torrent::Object resultRaw = torrent::Object::create_list();
|
||||
torrent::Object::list_type& result = resultRaw.as_list();
|
||||
|
||||
for (auto download : dlist) {
|
||||
for (const auto& download : dlist) {
|
||||
if (download.use_count() == 1)
|
||||
continue;
|
||||
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||
// A command may erase this download, which destroys the torrent object it
|
||||
// wraps; the list dropping its reference is what tells us.
|
||||
if (download.use_count() == 1)
|
||||
break;
|
||||
|
||||
auto& cmd = cItr->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(download), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||
}
|
||||
@@ -271,10 +281,12 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
|
||||
if (view_itr == viewManager->end())
|
||||
throw torrent::input_error("Could not find view '" + arg->as_string() + "'.");
|
||||
|
||||
// Make a filtered copy of the current item list
|
||||
// Make a filtered copy of the current item list, holding a reference to each
|
||||
// download so a command that erases one cannot free it under us.
|
||||
core::View::base_type dlist;
|
||||
(*view_itr)->filter_by(*++arg, dlist);
|
||||
|
||||
|
||||
// Generate result by iterating over all items
|
||||
auto resultRaw = torrent::Object::create_list();
|
||||
auto& result = resultRaw.as_list();
|
||||
@@ -282,11 +294,17 @@ d_multicall_filtered(const torrent::Object::list_type& args) {
|
||||
++arg; // skip to first command
|
||||
|
||||
for (const auto& item : dlist) {
|
||||
if (item.use_count() == 1)
|
||||
continue;
|
||||
|
||||
// Add empty row to result
|
||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||
|
||||
// Call the provided commands and assemble their results
|
||||
for (torrent::Object::list_const_iterator command = arg; command != args.end(); command++) {
|
||||
if (item.use_count() == 1)
|
||||
break;
|
||||
|
||||
auto& cmdstr = command->as_string();
|
||||
row.push_back(rpc::parse_command(rpc::make_target(item), cmdstr.c_str(), cmdstr.c_str() + cmdstr.size()).first);
|
||||
}
|
||||
|
||||
@@ -68,11 +68,11 @@ apply_dht_add_node(const std::string& arg) {
|
||||
torrent::Object
|
||||
apply_enable_trackers(int64_t arg) {
|
||||
if (arg == 0) {
|
||||
for (auto download : *control->core()->download_list())
|
||||
for (const auto& download : *control->core()->download_list())
|
||||
download->tracker_controller().for_each([](auto& tracker) { tracker.disable(); });
|
||||
|
||||
} else {
|
||||
for (auto download : *control->core()->download_list())
|
||||
for (const auto& download : *control->core()->download_list())
|
||||
download->tracker_controller().for_each([](auto& tracker) { tracker.enable(); });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef RTORRENT_CORE_DOWNLOAD_H
|
||||
#define RTORRENT_CORE_DOWNLOAD_H
|
||||
|
||||
#include <memory>
|
||||
#include <torrent/common.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/download_info.h>
|
||||
|
||||
+10
-12
@@ -37,7 +37,7 @@ namespace core {
|
||||
inline void
|
||||
DownloadList::check_contains([[maybe_unused]] Download* d) {
|
||||
#ifdef USE_EXTRA_DEBUG
|
||||
if (std::find(begin(), end(), d) == end())
|
||||
if (std::find_if(begin(), end(), [d](const auto& entry) { return entry.get() == d; }) == end())
|
||||
throw torrent::internal_error("DownloadList::check_contains(...) failed.");
|
||||
#endif
|
||||
}
|
||||
@@ -54,7 +54,6 @@ DownloadList::clear() {
|
||||
base_type::pop_back();
|
||||
|
||||
torrent::download_remove(*download->download());
|
||||
delete download;
|
||||
|
||||
} catch (torrent::internal_error& e) {
|
||||
lt_log_print(torrent::LOG_ERROR, "DownloadList::clear() failed to close or remove download: %s", e.what());
|
||||
@@ -70,7 +69,7 @@ DownloadList::clear() {
|
||||
void
|
||||
DownloadList::session_save() {
|
||||
for (auto& download : *this)
|
||||
session_thread::manager()->save_resume_download(download);
|
||||
session_thread::manager()->save_resume_download(download.get());
|
||||
|
||||
control->dht_manager()->save_dht_cache();
|
||||
control->ui()->save_input_history();
|
||||
@@ -78,7 +77,7 @@ DownloadList::session_save() {
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::find(const torrent::HashString& hash) {
|
||||
return std::find_if(begin(), end(), [hash](Download* d) { return hash == d->info()->hash(); });
|
||||
return std::find_if(begin(), end(), [hash](const auto& d) { return hash == d->info()->hash(); });
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
@@ -91,14 +90,14 @@ DownloadList::find_hex(const char* hash) {
|
||||
if (torrent::utils::transform_from_hex(hash, hash + 40, key) != key.end())
|
||||
return end();
|
||||
|
||||
return std::find_if(begin(), end(), [key](Download* d) { return key == d->info()->hash(); });
|
||||
return std::find_if(begin(), end(), [key](const auto& d) { return key == d->info()->hash(); });
|
||||
}
|
||||
|
||||
Download*
|
||||
DownloadList::find_hex_ptr(const char* hash) {
|
||||
iterator itr = find_hex(hash);
|
||||
|
||||
return itr != end() ? *itr : NULL;
|
||||
return itr != end() ? itr->get() : NULL;
|
||||
}
|
||||
|
||||
Download*
|
||||
@@ -159,7 +158,7 @@ DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::insert(Download* download) {
|
||||
iterator itr = base_type::insert(end(), download);
|
||||
iterator itr = base_type::insert(end(), std::shared_ptr<Download>(download));
|
||||
|
||||
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Inserting download.");
|
||||
|
||||
@@ -170,7 +169,7 @@ DownloadList::insert(Download* download) {
|
||||
// This needs to be separated into two different calls to ensure
|
||||
// the download remains in the view.
|
||||
for (auto v : *control->view_manager())
|
||||
v->insert(download);
|
||||
v->insert(*itr);
|
||||
for (auto v : *control->view_manager())
|
||||
v->filter_download(download);
|
||||
|
||||
@@ -187,7 +186,7 @@ DownloadList::insert(Download* download) {
|
||||
|
||||
void
|
||||
DownloadList::erase_ptr(Download* download) {
|
||||
erase(std::find(begin(), end(), download));
|
||||
erase(std::find_if(begin(), end(), [download](const auto& entry) { return entry.get() == download; }));
|
||||
}
|
||||
|
||||
DownloadList::iterator
|
||||
@@ -201,15 +200,14 @@ DownloadList::erase(iterator itr) {
|
||||
(*itr)->set_hash_failed(true);
|
||||
|
||||
close(*itr);
|
||||
session_thread::manager()->remove_download(*itr);
|
||||
session_thread::manager()->remove_download(itr->get());
|
||||
|
||||
DL_TRIGGER_EVENT(*itr, "event.download.erased");
|
||||
|
||||
for (auto v : *control->view_manager())
|
||||
v->erase(*itr);
|
||||
v->erase(itr->get());
|
||||
|
||||
torrent::download_remove(*(*itr)->download());
|
||||
delete *itr;
|
||||
|
||||
return base_type::erase(itr);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <iosfwd>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace torrent {
|
||||
@@ -20,9 +21,9 @@ class Download;
|
||||
//
|
||||
// Fix apply_on_ratio if the base_type is changed.
|
||||
|
||||
class DownloadList : private std::list<Download*> {
|
||||
class DownloadList : private std::list<std::shared_ptr<Download>> {
|
||||
public:
|
||||
typedef std::list<Download*> base_type;
|
||||
typedef std::list<std::shared_ptr<Download>> base_type;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
@@ -64,6 +65,14 @@ public:
|
||||
bool open(Download* d);
|
||||
void open_throw(Download* d);
|
||||
|
||||
// Overloads for the list's own entries, so callers iterating it do not need
|
||||
// to unwrap.
|
||||
bool open(const value_type& d) { return open(d.get()); }
|
||||
void close(const value_type& d) { close(d.get()); }
|
||||
void close_quick(const value_type& d) { close_quick(d.get()); }
|
||||
void pause(const value_type& d) { pause(d.get()); }
|
||||
void resume(const value_type& d) { resume(d.get()); }
|
||||
|
||||
void close(Download* d);
|
||||
void close_directly(Download* d);
|
||||
void close_quick(Download* d);
|
||||
|
||||
+4
-4
@@ -154,10 +154,10 @@ Manager::cleanup() {
|
||||
void
|
||||
Manager::shutdown(bool force) {
|
||||
if (!force) {
|
||||
for (auto d : *m_download_list)
|
||||
m_download_list->pause_default(d);
|
||||
for (const auto& d : *m_download_list)
|
||||
m_download_list->pause_default(d.get());
|
||||
} else {
|
||||
for (auto d : *m_download_list)
|
||||
for (const auto& d : *m_download_list)
|
||||
m_download_list->close_quick(d);
|
||||
}
|
||||
}
|
||||
@@ -405,7 +405,7 @@ Manager::receive_hashing_changed() {
|
||||
continue;
|
||||
|
||||
try {
|
||||
m_download_list->open_throw(*itr);
|
||||
m_download_list->open_throw(itr->get());
|
||||
|
||||
// Since the bitfield is allocated on loading of resume load or
|
||||
// hash start, and unallocated on close, we know that if it it
|
||||
|
||||
+40
-16
@@ -16,10 +16,20 @@
|
||||
namespace core {
|
||||
|
||||
// Also add focus thingie here?
|
||||
// Matches the list entry that owns a given download.
|
||||
inline auto
|
||||
entry_is(Download* download) {
|
||||
return [download](const std::shared_ptr<Download>& entry) { return entry.get() == download; };
|
||||
}
|
||||
|
||||
struct view_downloads_compare {
|
||||
view_downloads_compare(const torrent::Object& cmd) :
|
||||
m_command(cmd) {}
|
||||
|
||||
bool operator()(const std::shared_ptr<Download>& d1, const std::shared_ptr<Download>& d2) const {
|
||||
return (*this)(d1.get(), d2.get());
|
||||
}
|
||||
|
||||
bool operator()(Download* d1, Download* d2) const {
|
||||
try {
|
||||
if (m_command.is_empty())
|
||||
@@ -54,6 +64,10 @@ struct view_downloads_filter {
|
||||
view_downloads_filter(const torrent::Object& cmd, const torrent::Object& cmd2) :
|
||||
m_command(cmd), m_command2(cmd2) {}
|
||||
|
||||
bool operator()(const std::shared_ptr<Download>& d1) const {
|
||||
return (*this)(d1.get());
|
||||
}
|
||||
|
||||
bool operator()(Download* d1) const {
|
||||
return this->evalCmd(m_command, d1) && this->evalCmd(m_command2, d1);
|
||||
}
|
||||
@@ -152,7 +166,7 @@ View::initialize(const std::string& name) {
|
||||
|
||||
void
|
||||
View::erase(Download* download) {
|
||||
iterator itr = std::find(base_type::begin(), base_type::end(), download);
|
||||
iterator itr = std::find_if(base_type::begin(), base_type::end(), entry_is(download));
|
||||
|
||||
if (itr >= end_visible()) {
|
||||
erase_internal(itr);
|
||||
@@ -165,22 +179,24 @@ View::erase(Download* download) {
|
||||
|
||||
void
|
||||
View::set_visible(Download* download) {
|
||||
iterator itr = std::find(begin_filtered(), end_filtered(), download);
|
||||
iterator itr = std::find_if(begin_filtered(), end_filtered(), entry_is(download));
|
||||
|
||||
if (itr == end_filtered())
|
||||
return;
|
||||
|
||||
// Don't optimize erase since we want to keep the order of the
|
||||
// non-visible elements.
|
||||
auto entry = *itr;
|
||||
|
||||
base_type::erase(itr);
|
||||
insert_visible(download);
|
||||
insert_visible(entry);
|
||||
|
||||
rpc::call_object_nothrow(m_event_added, rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
View::set_not_visible(Download* download) {
|
||||
iterator itr = std::find(begin_visible(), end_visible(), download);
|
||||
iterator itr = std::find_if(begin_visible(), end_visible(), entry_is(download));
|
||||
|
||||
if (itr == end_visible())
|
||||
return;
|
||||
@@ -190,8 +206,10 @@ View::set_not_visible(Download* download) {
|
||||
|
||||
// Don't optimize erase since we want to keep the order of the
|
||||
// non-visible elements.
|
||||
auto entry = *itr;
|
||||
|
||||
base_type::erase(itr);
|
||||
base_type::push_back(download);
|
||||
base_type::push_back(entry);
|
||||
|
||||
rpc::call_object_nothrow(m_event_removed, rpc::make_target(download));
|
||||
}
|
||||
@@ -241,12 +259,12 @@ View::prev_focus(unsigned int i) {
|
||||
|
||||
void
|
||||
View::sort() {
|
||||
Download* curFocus = focus() != end_visible() ? *focus() : NULL;
|
||||
Download* curFocus = focus() != end_visible() ? focus()->get() : NULL;
|
||||
|
||||
// Don't go randomly switching around equivalent elements.
|
||||
std::stable_sort(begin(), end_visible(), view_downloads_compare(m_sortCurrent));
|
||||
|
||||
m_focus = position(std::find(begin(), end_visible(), curFocus));
|
||||
m_focus = position(std::find_if(begin(), end_visible(), entry_is(curFocus)));
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
@@ -280,10 +298,10 @@ View::filter() {
|
||||
// set the elements to NULL as we trigger commands on them. Or
|
||||
// perhaps always clear them, thus not throwing anything.
|
||||
if (!m_event_removed.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_removed, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, [this](const auto& d) { rpc::call_object_d_nothrow(m_event_removed, d.get()); });
|
||||
|
||||
if (!m_event_added.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged, std::bind(&rpc::call_object_d_nothrow, m_event_added, std::placeholders::_1));
|
||||
std::for_each(changed.begin(), splitChanged, [this](const auto& d) { rpc::call_object_d_nothrow(m_event_added, d.get()); });
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
@@ -294,21 +312,23 @@ View::filter_by(const torrent::Object& condition, View::base_type& result) {
|
||||
view_downloads_filter matches = view_downloads_filter(condition, m_temp_filter);
|
||||
|
||||
for (iterator itr = begin_visible(); itr != end_visible(); ++itr)
|
||||
if (matches(*itr))
|
||||
if (matches(itr->get()))
|
||||
result.push_back(*itr);
|
||||
}
|
||||
|
||||
void
|
||||
View::filter_download(core::Download* download) {
|
||||
iterator itr = std::find(base_type::begin(), base_type::end(), download);
|
||||
iterator itr = std::find_if(base_type::begin(), base_type::end(), entry_is(download));
|
||||
|
||||
if (itr == base_type::end())
|
||||
throw torrent::internal_error("View::filter_download(...) could not find download.");
|
||||
|
||||
if (view_downloads_filter(m_filter, m_temp_filter)(download)) {
|
||||
if (itr >= end_visible()) {
|
||||
auto entry = *itr;
|
||||
|
||||
erase_internal(itr);
|
||||
insert_visible(download);
|
||||
insert_visible(entry);
|
||||
|
||||
rpc::call_object_nothrow(m_event_added, rpc::make_target(download));
|
||||
|
||||
@@ -317,16 +337,20 @@ View::filter_download(core::Download* download) {
|
||||
// already visible.
|
||||
//
|
||||
// Consider removing this.
|
||||
auto entry = *itr;
|
||||
|
||||
erase_internal(itr);
|
||||
insert_visible(download);
|
||||
insert_visible(entry);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (itr >= end_visible())
|
||||
return;
|
||||
|
||||
auto entry = *itr;
|
||||
|
||||
erase_internal(itr);
|
||||
base_type::push_back(download);
|
||||
base_type::push_back(entry);
|
||||
|
||||
rpc::call_object_nothrow(m_event_removed, rpc::make_target(download));
|
||||
}
|
||||
@@ -345,8 +369,8 @@ View::clear_filter_on() {
|
||||
}
|
||||
|
||||
inline void
|
||||
View::insert_visible(Download* d) {
|
||||
auto itr = std::find_if(begin_visible(), end_visible(), [this, d](auto d2) { return view_downloads_compare(m_sortNew)(d, d2); });
|
||||
View::insert_visible(const std::shared_ptr<Download>& d) {
|
||||
auto itr = std::find_if(begin_visible(), end_visible(), [this, &d](const auto& d2) { return view_downloads_compare(m_sortNew)(d.get(), d2.get()); });
|
||||
|
||||
m_size++;
|
||||
m_focus += (m_focus >= position(itr));
|
||||
|
||||
+6
-5
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <torrent/object.h>
|
||||
@@ -26,9 +27,9 @@ namespace core {
|
||||
|
||||
class Download;
|
||||
|
||||
class View : private std::vector<Download*> {
|
||||
class View : private std::vector<std::shared_ptr<Download>> {
|
||||
public:
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef std::vector<std::shared_ptr<Download>> base_type;
|
||||
typedef std::function<void()> slot_void;
|
||||
typedef std::list<slot_void> signal_void;
|
||||
|
||||
@@ -72,7 +73,7 @@ public:
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void insert(Download* download) { base_type::push_back(download); }
|
||||
void insert(const std::shared_ptr<Download>& download) { base_type::push_back(download); }
|
||||
void erase(Download* download);
|
||||
|
||||
void set_visible(Download* download);
|
||||
@@ -124,9 +125,9 @@ private:
|
||||
View(const View&);
|
||||
void operator=(const View&);
|
||||
|
||||
void push_back(Download* d) { base_type::push_back(d); }
|
||||
void push_back(const std::shared_ptr<Download>& d) { base_type::push_back(d); }
|
||||
|
||||
inline void insert_visible(Download* d);
|
||||
inline void insert_visible(const std::shared_ptr<Download>& d);
|
||||
inline void erase_internal(iterator itr);
|
||||
|
||||
void emit_changed();
|
||||
|
||||
@@ -37,7 +37,7 @@ WindowDownloadList::set_view(core::View* l) {
|
||||
// Return a pair of ints, representing a) the ncurses attributes and b) the ncurses color pair ID to use
|
||||
std::pair<int, int>
|
||||
WindowDownloadList::get_attr_color(core::View::iterator selected) {
|
||||
core::Download* item = *selected;
|
||||
core::Download* item = selected->get();
|
||||
unsigned long focus_attr = selected == m_view->focus() ? m_canvas->attr_map().at(RCOLOR_FOCUS) : 0;
|
||||
int offset = (((selected - m_view->begin_visible()) & 1) + 1) * RCOLOR_MAX; // Determine the even/odd offset for the color pair
|
||||
bool active = item->is_open() && item->is_active();
|
||||
@@ -132,15 +132,15 @@ WindowDownloadList::redraw() {
|
||||
ColorKind focus_color = is_focused ? RCOLOR_FOCUS : RCOLOR_LABEL;
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_title(buffer.data(), last, *range.first);
|
||||
print_download_title(buffer.data(), last, range.first->get());
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
print_download_info_full(buffer.data(), last, *range.first);
|
||||
print_download_info_full(buffer.data(), last, range.first->get());
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
print_download_status(buffer.data(), last, *range.first);
|
||||
print_download_status(buffer.data(), last, range.first->get());
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
|
||||
m_canvas->set_attr(2, pos++, -1, focus_color);
|
||||
|
||||
@@ -152,7 +152,7 @@ WindowDownloadList::redraw() {
|
||||
char focus_char = range.first == m_view->focus() ? '*' : ' ';
|
||||
auto attr_color = get_attr_color(range.first);
|
||||
|
||||
print_download_info_compact(buffer.data(), last, *range.first);
|
||||
print_download_info_compact(buffer.data(), last, range.first->get());
|
||||
m_canvas->print(0, pos, "%c %s", focus_char, buffer.data());
|
||||
m_canvas->set_attr(2, pos++, -1, attr_color.first, attr_color.second);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef RTORRENT_RPC_COMMAND_MAP_H
|
||||
#define RTORRENT_RPC_COMMAND_MAP_H
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
@@ -104,6 +105,10 @@ inline target_type make_target(T target) {
|
||||
return target_type((int)target_type_id<T>::value, target);
|
||||
}
|
||||
|
||||
inline target_type make_target(const std::shared_ptr<core::Download>& target) {
|
||||
return make_target(target.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline target_type make_target_pair(T target1, T target2) {
|
||||
return target_type((int)target_type_id<T, T>::value, target1, target2);
|
||||
|
||||
+5
-2
@@ -1,3 +1,4 @@
|
||||
#include <memory>
|
||||
#include "config.h"
|
||||
|
||||
#include <cassert>
|
||||
@@ -30,8 +31,10 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
Download::Download(core::Download* d)
|
||||
: m_download(d) {
|
||||
Download::Download(const std::shared_ptr<core::Download>& download)
|
||||
: m_download(download.get()) {
|
||||
|
||||
auto* d = download.get();
|
||||
|
||||
m_windowDownloadStatus = std::make_unique<WDownloadStatus>(d);
|
||||
m_windowDownloadStatus->set_bottom(true);
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@
|
||||
#define RTORRENT_UI_DOWNLOAD_H
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <torrent/peer/peer.h>
|
||||
|
||||
#include "display/manager.h"
|
||||
@@ -36,7 +37,7 @@ public:
|
||||
DISPLAY_MAX_SIZE
|
||||
} Display;
|
||||
|
||||
Download(core::Download* d);
|
||||
Download(const std::shared_ptr<core::Download>& d);
|
||||
~Download();
|
||||
|
||||
void activate(display::Frame* frame, bool focus = true);
|
||||
|
||||
@@ -89,7 +89,7 @@ DownloadList::unfocus_download(core::Download* d) {
|
||||
if (m_state == DISPLAY_DOWNLOAD && d == static_cast<Download*>(m_uiArray[DISPLAY_DOWNLOAD])->download())
|
||||
activate_display(DISPLAY_DOWNLOAD_LIST);
|
||||
|
||||
if (current_view()->focus() < current_view()->end_visible() && *current_view()->focus() == d)
|
||||
if (current_view()->focus() < current_view()->end_visible() && current_view()->focus()->get() == d)
|
||||
current_view()->next_focus();
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ ElementDownloadList::receive_cycle_throttle() {
|
||||
if (m_view->focus() == m_view->end_visible())
|
||||
return;
|
||||
|
||||
core::Download* download = *m_view->focus();
|
||||
core::Download* download = m_view->focus()->get();
|
||||
if (download->is_active()) {
|
||||
lt_log_print(torrent::LOG_TORRENT_WARN, "Cannot change throttle on active download.");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user