diff --git a/src/control.cc b/src/control.cc index e946b677..5414c0a9 100644 --- a/src/control.cc +++ b/src/control.cc @@ -74,8 +74,8 @@ Control::Control() : m_tick(0) { m_core = new core::Manager(); - m_viewManager = new core::ViewManager(&m_core->download_list()); - m_scheduler = new core::Scheduler(&m_core->download_list()); + m_viewManager = new core::ViewManager(m_core->download_list()); + m_scheduler = new core::Scheduler(m_core->download_list()); m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed)); diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 706f660b..fcb4f9b1 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -30,8 +30,8 @@ libsub_core_a_SOURCES = \ poll_manager_select.h \ scheduler.cc \ scheduler.h \ - view_downloads.cc \ - view_downloads.h \ + view.cc \ + view.h \ view_manager.cc \ view_manager.h diff --git a/src/core/download.cc b/src/core/download.cc index 966b6939..c1e65560 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -71,6 +71,7 @@ Download::Download(download_type d) : m_variables.insert("connection_leech", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_LEECH))); m_variables.insert("connection_seed", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_SEED))); m_variables.insert("state", new utils::VariableObject(bencode(), "rtorrent", "state", torrent::Object::TYPE_VALUE)); + m_variables.insert("complete", new utils::VariableObject(bencode(), "rtorrent", "complete", torrent::Object::TYPE_VALUE)); m_variables.insert("tied_to_file", new utils::VariableObject(bencode(), "rtorrent", "tied_to_file", torrent::Object::TYPE_STRING)); // The "state_changed" variable is required to be a valid unix time @@ -102,25 +103,6 @@ Download::~Download() { m_download = download_type(); } -void -Download::start() { - if (is_done()) - m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string())); - else - m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_leech").as_string())); - - // Update the priority to ensure it has the correct - // seeding/unfinished modifiers. - set_priority(priority()); - - m_download.start(); -} - -void -Download::stop() { - m_download.stop(); -} - void Download::enable_udp_trackers(bool state) { torrent::TrackerList tl = m_download.tracker_list(); @@ -152,13 +134,6 @@ Download::set_priority(uint32_t p) { bencode()->get_key("rtorrent").insert_key("priority", (int64_t)p); } -void -Download::receive_finished() { - m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string())); - // FIXME - //torrent::download_set_priority(m_download, 2); -} - void Download::receive_tracker_msg(std::string msg) { if (msg.empty()) diff --git a/src/core/download.h b/src/core/download.h index bddadec7..d0dd4c7f 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -62,11 +62,6 @@ public: bool is_active() const { return m_download.is_active(); } inline bool is_done() const { return m_download.chunks_done() == m_download.chunks_total(); } - void start(); - void stop(); - - // Add functions like pause/etc. - variable_map_type* variable() { return &m_variables; } std::string variable_string(const std::string& key) { return m_variables.get_string(key); } @@ -97,7 +92,7 @@ public: bool operator == (const std::string& str) { return str == m_download.info_hash(); } - void receive_finished(); + void set_connection_type(const std::string& t) { m_download.set_connection_type(string_to_connection_type(t)); } static connection_type string_to_connection_type(const std::string& name); static const char* connection_type_to_string(connection_type t); diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 3b4ea7c2..b9d07aa0 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -141,7 +141,7 @@ DownloadFactory::receive_success() { if (m_stream == NULL) throw torrent::client_error("DownloadFactory::receive_success() called on an object with m_stream == NULL"); - Download* download = m_manager->download_list().create(m_stream, m_printLog); + Download* download = m_manager->download_list()->create(m_stream, m_printLog); if (download == NULL) { // core::Manager should already have added the error message to @@ -166,7 +166,7 @@ DownloadFactory::receive_success() { initialize_rtorrent(download, rtorrent); - if (m_manager->download_list().insert(download) == m_manager->download_list().end()) { + if (m_manager->download_list()->insert(download) == m_manager->download_list()->end()) { // ATM doesn't really ever get here. delete download; @@ -191,7 +191,7 @@ DownloadFactory::receive_success() { download->variable()->set("directory", rtorrent->get_key("directory")); if (download->variable()->get_value("state") == 1) - m_manager->download_list().resume(download); + m_manager->download_list()->resume(download); } else { download->variable()->set("directory", m_variables.get("directory")); @@ -201,7 +201,7 @@ DownloadFactory::receive_success() { // Use the state thingie here, move below. if (m_start) - m_manager->download_list().start(download); + m_manager->download_list()->start(download); m_manager->download_store().save(download); } @@ -234,6 +234,9 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre rtorrent->insert_key("state_changed", cachedTime.seconds()); } + if (!rtorrent->has_key_value("complete")) + rtorrent->insert_key("complete", (int64_t)0); + if (!rtorrent->has_key_string("tied_to_file")) rtorrent->insert_key("tied_to_file", std::string()); diff --git a/src/core/download_list.cc b/src/core/download_list.cc index 1e0404a9..74a5a665 100644 --- a/src/core/download_list.cc +++ b/src/core/download_list.cc @@ -47,17 +47,19 @@ #include "rak/functional.h" #include "globals.h" +#include "hash_queue.h" #include "manager.h" #include "download.h" #include "download_list.h" +#include "download_store.h" namespace core { struct download_list_call { download_list_call(Download* d) : m_download(d) {} - void operator () (const DownloadList::SlotMap::value_type& s) { + void operator () (const DownloadList::slot_map::value_type& s) { s.second(m_download); } @@ -94,10 +96,10 @@ DownloadList::create(std::istream* str, bool printLog) { DownloadList::iterator DownloadList::insert(Download* d) { - iterator itr = Base::insert(end(), d); + iterator itr = base_type::insert(end(), d); try { - (*itr)->download()->signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::finished), *itr)); + (*itr)->download()->signal_download_done(sigc::bind(sigc::mem_fun(*this, &DownloadList::received_finished), d)); std::for_each(m_slotMapInsert.begin(), m_slotMapInsert.end(), download_list_call(*itr)); } catch (torrent::local_error& e) { @@ -128,7 +130,7 @@ DownloadList::erase(iterator itr) { torrent::download_remove(*(*itr)->download()); delete *itr; - return Base::erase(itr); + return base_type::erase(itr); } void @@ -173,18 +175,32 @@ DownloadList::stop(Download* d) { } void -DownloadList::resume(Download* d) { +DownloadList::resume(Download* download) { try { - if (!d->download()->is_open()) - std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(d)); - - if (d->download()->is_hash_checked()) - std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(d)); - else - // TODO: This can cause infinit looping? - control->core()->hash_queue().insert(d, sigc::bind(sigc::mem_fun(*this, &DownloadList::resume), d)); - d->variable()->set("state_changed", cachedTime.seconds()); + if (!download->download()->is_open()) + std::for_each(m_slotMapOpen.begin(), m_slotMapOpen.end(), download_list_call(download)); + + if (download->download()->is_hash_checked()) { + + if (download->is_done()) + download->set_connection_type(download->variable()->get_string("connection_seed")); + else + download->set_connection_type(download->variable()->get_string("connection_leech")); + + // Update the priority to ensure it has the correct + // seeding/unfinished modifiers. + download->set_priority(download->priority()); + download->download()->start(); + + std::for_each(m_slotMapStart.begin(), m_slotMapStart.end(), download_list_call(download)); + + } else { + // TODO: This can cause infinit looping? + control->core()->hash_queue()->insert(download); + } + + download->variable()->set("state_changed", cachedTime.seconds()); } catch (torrent::local_error& e) { control->core()->push_log(e.what()); @@ -192,13 +208,20 @@ DownloadList::resume(Download* d) { } void -DownloadList::pause(Download* d) { +DownloadList::pause(Download* download) { try { - if (d->download()->is_active()) - std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(d)); + download->download()->stop(); + download->download()->hash_resume_save(); + + if (download->download()->is_active()) + std::for_each(m_slotMapStop.begin(), m_slotMapStop.end(), download_list_call(download)); - d->variable()->set("state_changed", cachedTime.seconds()); + download->variable()->set("state_changed", cachedTime.seconds()); + + // Save the state after all the slots, etc have been called so we + // include the modifications they may make. + control->core()->download_store().save(download); } catch (torrent::local_error& e) { control->core()->push_log(e.what()); @@ -209,12 +232,70 @@ void DownloadList::clear() { std::for_each(begin(), end(), rak::call_delete()); - Base::clear(); + base_type::clear(); } void -DownloadList::finished(Download* d) { - std::for_each(m_slotMapFinished.begin(), m_slotMapFinished.end(), download_list_call(d)); +DownloadList::check_hash(Download* d) { + close(d); + d->download()->hash_resume_clear(); + open(d); + + control->core()->hash_queue()->insert(d); +} + +void +DownloadList::hash_done(Download* download) { + if (!download->download()->is_hash_checked() || download->download()->is_hash_checking()) + throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state."); + + // Need to find some sane conditional here. Can we check the total + // downloaded to ensure something was transferred, thus we didn't + // just hash an already completed torrent with lacking session data? + // + // Perhaps we should use a seperate variable or state, and check + // that. Thus we can bork the download if the hash check doesn't + // confirm all the data, avoiding large BW usage on f.ex. the + // ReiserFS bug with >4GB files. + + // Use just is_done(), have another if statement inside. + if (download->is_done() && download->variable()->get_value("complete") == 0) { + + if (control->variable()->get_value("session_on_completion")) + control->core()->download_store().save(download); + + // Send a "truly finished message from here. + confirm_finished(download); + } + + if (download->variable()->get_value("state") == 1) + resume(download); +} + +void +DownloadList::received_finished(Download* download) { + if (control->variable()->get_value("check_hash")) { + // Set some 'checking_finished_thingie' variable to make hash_done + // trigger correctly, also so it can bork on missing data. + + check_hash(download); + + } else { + confirm_finished(download); + } +} + +void +DownloadList::confirm_finished(Download* download) { + // FIXME + //torrent::download_set_priority(m_download, 2); + + download->variable()->set("complete", (int64_t)1); + download->set_connection_type(download->variable()->get_string("connection_seed")); + + download->download()->tracker_list().send_completed(); + + std::for_each(m_slotMapFinished.begin(), m_slotMapFinished.end(), download_list_call(download)); } } diff --git a/src/core/download_list.h b/src/core/download_list.h index 577a2e6d..a8735820 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -53,23 +53,24 @@ class Download; class DownloadList : private std::list { public: - typedef std::list Base; - typedef std::map > SlotMap; + typedef std::list base_type; + typedef sigc::slot1 slot_type; + typedef std::map slot_map; - using Base::iterator; - using Base::const_iterator; - using Base::reverse_iterator; - using Base::const_reverse_iterator; - using Base::value_type; - using Base::pointer; + using base_type::iterator; + using base_type::const_iterator; + using base_type::reverse_iterator; + using base_type::const_reverse_iterator; + using base_type::value_type; + using base_type::pointer; - using Base::begin; - using Base::end; - using Base::rbegin; - using Base::rend; + using base_type::begin; + using base_type::end; + using base_type::rbegin; + using base_type::rend; - using Base::empty; - using Base::size; + using base_type::empty; + using base_type::size; ~DownloadList() { clear(); } @@ -91,37 +92,52 @@ public: void resume(Download* d); void pause(Download* d); - SlotMap& slot_map_insert() { return m_slotMapInsert; } - SlotMap& slot_map_erase() { return m_slotMapErase; } - SlotMap& slot_map_open() { return m_slotMapOpen; } - SlotMap& slot_map_close() { return m_slotMapClose; } - SlotMap& slot_map_start() { return m_slotMapStart; } - SlotMap& slot_map_stop() { return m_slotMapStop; } + void check_hash(Download* d); + void hash_done(Download* d); - SlotMap& slot_map_finished() { return m_slotMapFinished; } + slot_map& slot_map_insert() { return m_slotMapInsert; } + slot_map& slot_map_erase() { return m_slotMapErase; } + slot_map& slot_map_open() { return m_slotMapOpen; } + slot_map& slot_map_close() { return m_slotMapClose; } + slot_map& slot_map_start() { return m_slotMapStart; } + slot_map& slot_map_stop() { return m_slotMapStop; } - bool has_slot_insert(const std::string& key) const { return m_slotMapInsert.find(key) != m_slotMapInsert.end(); } - bool has_slot_erase(const std::string& key) const { return m_slotMapErase.find(key) != m_slotMapErase.end(); } - bool has_slot_open(const std::string& key) const { return m_slotMapOpen.find(key) != m_slotMapOpen.end(); } - bool has_slot_close(const std::string& key) const { return m_slotMapClose.find(key) != m_slotMapClose.end(); } - bool has_slot_start(const std::string& key) const { return m_slotMapStart.find(key) != m_slotMapStart.end(); } - bool has_slot_stop(const std::string& key) const { return m_slotMapStop.find(key) != m_slotMapStop.end(); } + // The finished slots will be called when an active download with + // "finished" == 0 performs a hash check which returns a done + // torrent. + // + // But how to avoid sending 'completed' messages to the tracker? + // Also we need to handle cases when a hashing torrent starts up + // after a shutdown. - bool has_slot_finished(const std::string& key) const { return m_slotMapFinished.find(key) != m_slotMapFinished.end(); } + slot_map& slot_map_hash_done() { return m_slotMapHashDone; } + slot_map& slot_map_finished() { return m_slotMapFinished; } + + bool has_slot_insert(const std::string& key) const { return m_slotMapInsert.find(key) != m_slotMapInsert.end(); } + bool has_slot_erase(const std::string& key) const { return m_slotMapErase.find(key) != m_slotMapErase.end(); } + bool has_slot_open(const std::string& key) const { return m_slotMapOpen.find(key) != m_slotMapOpen.end(); } + bool has_slot_close(const std::string& key) const { return m_slotMapClose.find(key) != m_slotMapClose.end(); } + bool has_slot_start(const std::string& key) const { return m_slotMapStart.find(key) != m_slotMapStart.end(); } + bool has_slot_stop(const std::string& key) const { return m_slotMapStop.find(key) != m_slotMapStop.end(); } + + bool has_slot_hash_done(const std::string& key) const { return m_slotMapFinished.find(key) != m_slotMapFinished.end(); } + bool has_slot_finished(const std::string& key) const { return m_slotMapFinished.find(key) != m_slotMapFinished.end(); } private: void clear(); - void finished(Download* d); + void received_finished(Download* d); + void confirm_finished(Download* d); - SlotMap m_slotMapInsert; - SlotMap m_slotMapErase; - SlotMap m_slotMapOpen; - SlotMap m_slotMapClose; - SlotMap m_slotMapStart; - SlotMap m_slotMapStop; + slot_map m_slotMapInsert; + slot_map m_slotMapErase; + slot_map m_slotMapOpen; + slot_map m_slotMapClose; + slot_map m_slotMapStart; + slot_map m_slotMapStop; - SlotMap m_slotMapFinished; + slot_map m_slotMapHashDone; + slot_map m_slotMapFinished; }; } diff --git a/src/core/hash_queue.cc b/src/core/hash_queue.cc index 0eac350c..86f3797c 100644 --- a/src/core/hash_queue.cc +++ b/src/core/hash_queue.cc @@ -41,26 +41,29 @@ #include #include "download.h" +#include "download_list.h" #include "rak/functional.h" #include "hash_queue.h" namespace core { void -HashQueue::insert(Download* d, Slot s) { - if (d->download()->is_hash_checking() || - find(d) != end()) +HashQueue::insert(Download* download) { + if (download->download()->is_hash_checking() || + find(download) != end()) return; - if (d->download()->is_hash_checked()) { - s(); + if (download->download()->is_hash_checked()) { + m_downloadList->hash_done(download); return; } - iterator itr = Base::insert(end(), new HashQueueNode(d, s)); + if (find(download) != end()) + throw torrent::internal_error("HashQueue::insert(...) download already in queue."); - (*itr)->set_connection(d->download()->signal_hash_done(sigc::bind(sigc::mem_fun(*this, &HashQueue::receive_hash_done), - (*itr)->download()))); + iterator itr = Base::insert(end(), new HashQueueNode(download)); + + (*itr)->set_connection(download->download()->signal_hash_done(sigc::bind(sigc::mem_fun(*this, &HashQueue::receive_hash_done), download))); fill_queue(); } @@ -95,13 +98,10 @@ HashQueue::receive_hash_done(Download* d) { if (itr == end()) return; - Slot s = (*itr)->get_slot(); - delete *itr; Base::erase(itr); - // Can we call this before the delete? - s(); + m_downloadList->hash_done(d); fill_queue(); } diff --git a/src/core/hash_queue.h b/src/core/hash_queue.h index fba85833..c4ddf920 100644 --- a/src/core/hash_queue.h +++ b/src/core/hash_queue.h @@ -44,13 +44,13 @@ namespace core { class Download; +class DownloadList; class HashQueueNode; class HashQueue : private std::list { public: typedef std::list Base; - typedef sigc::slot0 Slot; using Base::iterator; using Base::const_iterator; @@ -68,7 +68,10 @@ public: using Base::empty; using Base::size; - void insert(Download* d, Slot s); + // Replace 'dl' with a slot. + HashQueue(DownloadList* dl) : m_downloadList(dl) {} + + void insert(Download* d); // It's safe to try to remove downloads not in the queue. The hash // checking is not stopped if it has already started. @@ -80,23 +83,22 @@ private: void receive_hash_done(Download* d); void fill_queue(); + + DownloadList* m_downloadList; }; class HashQueueNode { public: - HashQueueNode(Download* d, HashQueue::Slot s) : m_download(d), m_slot(s) {} + HashQueueNode(Download* d) : m_download(d) {} ~HashQueueNode() { disconnect(); } void disconnect() { m_connection.disconnect(); } - Download* download() { return m_download; } - HashQueue::Slot get_slot() { return m_slot; } void set_connection(sigc::connection c) { m_connection = c; } private: Download* m_download; - HashQueue::Slot m_slot; sigc::connection m_connection; }; diff --git a/src/core/manager.cc b/src/core/manager.cc index d2f16abe..d3148403 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -59,6 +59,7 @@ #include "curl_get.h" #include "download.h" #include "download_factory.h" +#include "hash_queue.h" #include "manager.h" #include "poll_manager_epoll.h" #include "poll_manager_select.h" @@ -114,6 +115,14 @@ Manager::Manager() : m_pollManager(NULL), m_portFirst(6890), m_portLast(6999) { + + m_downloadList = new DownloadList(); + m_hashQueue = new HashQueue(m_downloadList); +} + +Manager::~Manager() { + delete m_hashQueue; + delete m_downloadList; } void @@ -139,29 +148,20 @@ Manager::initialize_second() { // Register slots to be called when a download is inserted/erased, // opened or closed. - m_downloadList.slot_map_insert()["1_connect_network_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_network_log), sigc::mem_fun(m_logComplete, &Log::push_front)); - m_downloadList.slot_map_insert()["1_connect_storage_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_storage_log), sigc::mem_fun(m_logComplete, &Log::push_front)); - m_downloadList.slot_map_insert()["1_connect_tracker_dump"] = sigc::bind(sigc::ptr_fun(&connect_signal_tracker_dump), sigc::ptr_fun(&receive_tracker_dump)); + m_downloadList->slot_map_insert()["1_connect_network_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_network_log), sigc::mem_fun(m_logComplete, &Log::push_front)); + m_downloadList->slot_map_insert()["1_connect_storage_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_storage_log), sigc::mem_fun(m_logComplete, &Log::push_front)); + m_downloadList->slot_map_insert()["1_connect_tracker_dump"] = sigc::bind(sigc::ptr_fun(&connect_signal_tracker_dump), sigc::ptr_fun(&receive_tracker_dump)); - m_downloadList.slot_map_erase()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); - m_downloadList.slot_map_erase()["1_store_remove"] = sigc::mem_fun(m_downloadStore, &DownloadStore::remove); - m_downloadList.slot_map_erase()["1_delete_tied"] = sigc::ptr_fun(&delete_tied); + m_downloadList->slot_map_erase()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); + m_downloadList->slot_map_erase()["1_store_remove"] = sigc::mem_fun(m_downloadStore, &DownloadStore::remove); + m_downloadList->slot_map_erase()["1_delete_tied"] = sigc::ptr_fun(&delete_tied); - m_downloadList.slot_map_open()["1_download_open"] = sigc::mem_fun(&Download::call); + m_downloadList->slot_map_open()["1_download_open"] = sigc::mem_fun(&Download::call); // Currently does not call stop, might want to add a function that // checks if we're running, and if so stop? - m_downloadList.slot_map_close()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); - m_downloadList.slot_map_close()["2_download_close"] = sigc::mem_fun(&Download::call); - - m_downloadList.slot_map_start()["1_download_start"] = sigc::mem_fun(&Download::start); - - m_downloadList.slot_map_stop()["1_download_stop"] = sigc::mem_fun(&Download::stop); - m_downloadList.slot_map_stop()["2_hash_resume_save"] = sigc::mem_fun(&Download::call); - m_downloadList.slot_map_stop()["3_store_save"] = sigc::mem_fun(m_downloadStore, &DownloadStore::save); - - m_downloadList.slot_map_finished()["1_download_done"] = sigc::mem_fun(*this, &Manager::receive_download_done); - m_downloadList.slot_map_finished()["2_receive_finished"] = sigc::mem_fun(&Download::receive_finished); + m_downloadList->slot_map_close()["1_hash_queue_remove"] = sigc::mem_fun(m_hashQueue, &HashQueue::remove); + m_downloadList->slot_map_close()["2_download_close"] = sigc::mem_fun(&Download::call); } void @@ -178,42 +178,9 @@ Manager::cleanup() { void Manager::shutdown(bool force) { if (!force) - std::for_each(m_downloadList.begin(), m_downloadList.end(), std::bind1st(std::mem_fun(&DownloadList::pause), &m_downloadList)); + std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::pause), &m_downloadList)); else - std::for_each(m_downloadList.begin(), m_downloadList.end(), std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); -} - -void -Manager::check_hash(Download* d) { - bool restart = d->download()->is_active(); - - try { - prepare_hash_check(d); - - if (restart) - m_hashQueue.insert(d, sigc::bind(sigc::mem_fun(m_downloadList, &DownloadList::resume), d)); - else - m_hashQueue.insert(d, sigc::slot0()); - - } catch (torrent::local_error& e) { - m_logImportant.push_front(e.what()); - m_logComplete.push_front(e.what()); - } -} - -void -Manager::receive_download_done(Download* d) { - if (control->variable()->get_value("check_hash")) { - // Start the hash checking, send completed to tracker after - // finishing. - prepare_hash_check(d); - - // TODO: Need to restart the torrent. - m_hashQueue.insert(d, sigc::bind(sigc::mem_fun(*this, &Manager::receive_download_done_hash_checked), d)); - - } else { - receive_download_done_hash_checked(d); - } + std::for_each(m_downloadList->begin(), m_downloadList->end(), std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); } void @@ -297,38 +264,12 @@ Manager::set_local_address(const std::string& addr) { } } -void -Manager::prepare_hash_check(Download* d) { - m_downloadList.close(d); - d->download()->hash_resume_clear(); - m_downloadList.open(d); - - if (d->download()->is_hash_checking() || - d->download()->is_hash_checked()) - throw std::logic_error("Manager::check_hash(...) closed the torrent but is_hash_check{ing,ed}() == true"); - - if (m_hashQueue.find(d) != m_hashQueue.end()) - throw std::logic_error("Manager::check_hash(...) closed the torrent but it was found in m_hashQueue"); -} - void Manager::receive_http_failed(std::string msg) { m_logImportant.push_front("Http download error: \"" + msg + "\""); m_logComplete.push_front("Http download error: \"" + msg + "\""); } -void -Manager::receive_download_done_hash_checked(Download* d) { - m_downloadList.resume(d); - - if (control->variable()->get_value("session_on_completion")) - m_downloadStore.save(d); - - // Don't send if we did a hash check and found incompelete chunks. - if (d->is_done()) - d->download()->tracker_list().send_completed(); -} - void Manager::try_create_download(const std::string& uri, bool start, bool printLog, bool tied) { // Adding download. @@ -398,8 +339,8 @@ Manager::try_create_download_expand(const std::string& uri, bool start, bool pri if (tied) for (std::vector::iterator itr = paths.begin(); itr != paths.end(); ) - if (std::find_if(m_downloadList.begin(), m_downloadList.end(), - rak::equal(*itr, rak::bind2nd(std::mem_fun(&Download::variable_string), "tied_to_file"))) != m_downloadList.end()) + if (std::find_if(m_downloadList->begin(), m_downloadList->end(), + rak::equal(*itr, rak::bind2nd(std::mem_fun(&Download::variable_string), "tied_to_file"))) != m_downloadList->end()) itr = paths.erase(itr); else itr++; diff --git a/src/core/manager.h b/src/core/manager.h index 3371092f..11b646d1 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -41,7 +41,6 @@ #include "download_list.h" #include "download_store.h" -#include "hash_queue.h" #include "http_queue.h" #include "poll_manager.h" #include "log.h" @@ -52,6 +51,8 @@ namespace torrent { namespace core { +class HashQueue; + class Manager { public: typedef DownloadList::iterator DListItr; @@ -59,12 +60,14 @@ public: typedef sigc::slot0 SlotFailed; Manager(); + ~Manager(); - DownloadList& download_list() { return m_downloadList; } DownloadStore& download_store() { return m_downloadStore; } - HashQueue& hash_queue() { return m_hashQueue; } HttpQueue& http_queue() { return m_httpQueue; } + DownloadList* download_list() { return m_downloadList; } + HashQueue* hash_queue() { return m_hashQueue; } + PollManager* get_poll_manager() { return m_pollManager; } Log& get_log_important() { return m_logImportant; } Log& get_log_complete() { return m_logComplete; } @@ -86,8 +89,6 @@ public: void shutdown(bool force); - void check_hash(Download* d); - void push_log(const std::string& msg) { m_logImportant.push_front(msg); m_logComplete.push_front(msg); } // Temporary, find a better place for this. @@ -100,16 +101,11 @@ private: void initialize_bencode(Download* d); - void prepare_hash_check(Download* d); - void receive_http_failed(std::string msg); - void receive_download_done_hash_checked(Download* d); - void receive_download_inserted(Download* d); - void receive_download_done(Download* d); - DownloadList m_downloadList; + DownloadList* m_downloadList; DownloadStore m_downloadStore; - HashQueue m_hashQueue; + HashQueue* m_hashQueue; HttpQueue m_httpQueue; PollManager* m_pollManager; diff --git a/src/core/scheduler.cc b/src/core/scheduler.cc index a46c92a0..19c1cb9c 100644 --- a/src/core/scheduler.cc +++ b/src/core/scheduler.cc @@ -42,7 +42,7 @@ #include "download.h" #include "download_list.h" #include "scheduler.h" -#include "view_downloads.h" +#include "view.h" namespace core { @@ -59,7 +59,7 @@ Scheduler::~Scheduler() { } void -Scheduler::set_view(ViewDownloads* view) { +Scheduler::set_view(View* view) { m_view = view; } @@ -80,7 +80,7 @@ Scheduler::update() { // inactive we can switch with. size_type target = m_maxActive - std::min(m_cycle, m_maxActive); - for (ViewDownloads::iterator itr = m_view->begin(), last = m_view->end(); curActive > target; ++itr) { + for (View::iterator itr = m_view->begin(), last = m_view->end(); curActive > target; ++itr) { if (itr == last) throw torrent::internal_error("Scheduler::update() loop bork."); @@ -92,7 +92,7 @@ Scheduler::update() { m_view->sort(); - for (ViewDownloads::iterator itr = m_view->begin(), last = m_view->end(); curActive < m_maxActive; ++itr) { + for (View::iterator itr = m_view->begin(), last = m_view->end(); curActive < m_maxActive; ++itr) { if (itr == last) throw torrent::internal_error("Scheduler::update() loop bork."); diff --git a/src/core/scheduler.h b/src/core/scheduler.h index 9ed0b7d2..6de4d08d 100644 --- a/src/core/scheduler.h +++ b/src/core/scheduler.h @@ -41,12 +41,12 @@ #include #include -#include "view_downloads.h" +#include "view.h" namespace core { class DownloadList; -class ViewDownloads; +class View; class Scheduler { public: @@ -57,7 +57,7 @@ public: Scheduler(DownloadList* dl); ~Scheduler(); - void set_view(ViewDownloads* view); + void set_view(View* view); size_type max_active() const { return m_maxActive; } void set_max_active(size_type v) { m_maxActive = v; } @@ -70,7 +70,7 @@ public: void update(); private: - ViewDownloads* m_view; + View* m_view; DownloadList* m_downloadList; size_type m_maxActive; diff --git a/src/core/view_downloads.cc b/src/core/view.cc similarity index 75% rename from src/core/view_downloads.cc rename to src/core/view.cc index 60019789..a0b42713 100644 --- a/src/core/view_downloads.cc +++ b/src/core/view.cc @@ -43,11 +43,11 @@ #include "download.h" #include "download_list.h" -#include "view_downloads.h" +#include "view.h" namespace core { -ViewDownloads::~ViewDownloads() { +View::~View() { if (m_name.empty()) return; @@ -58,17 +58,17 @@ ViewDownloads::~ViewDownloads() { } void -ViewDownloads::initialize(const std::string& name, core::DownloadList* list) { +View::initialize(const std::string& name, core::DownloadList* list) { if (!m_name.empty()) - throw torrent::internal_error("ViewDownloads::initialize(...) called on an already initialized view."); + throw torrent::internal_error("View::initialize(...) called on an already initialized view."); if (name.empty()) - throw torrent::internal_error("ViewDownloads::initialize(...) called with an empty name."); + throw torrent::internal_error("View::initialize(...) called with an empty name."); std::string key = "0_view_" + name; if (list->has_slot_insert(key) || list->has_slot_erase(key)) - throw torrent::internal_error("ViewDownloads::initialize(...) duplicate key name found in DownloadList."); + throw torrent::internal_error("View::initialize(...) duplicate key name found in DownloadList."); m_name = name; @@ -78,14 +78,14 @@ ViewDownloads::initialize(const std::string& name, core::DownloadList* list) { set_last_changed(rak::timer()); - std::for_each(m_list->begin(), m_list->end(), std::bind1st(std::mem_fun(&ViewDownloads::received_insert), this)); + std::for_each(m_list->begin(), m_list->end(), std::bind1st(std::mem_fun(&View::received_insert), this)); - m_list->slot_map_insert()[key] = sigc::mem_fun(this, &ViewDownloads::received_insert); - m_list->slot_map_erase()[key] = sigc::mem_fun(this, &ViewDownloads::received_erase); + m_list->slot_map_insert()[key] = sigc::mem_fun(this, &View::received_insert); + m_list->slot_map_erase()[key] = sigc::mem_fun(this, &View::received_erase); } void -ViewDownloads::next_focus() { +View::next_focus() { if (empty()) return; @@ -95,7 +95,7 @@ ViewDownloads::next_focus() { } void -ViewDownloads::prev_focus() { +View::prev_focus() { if (empty()) return; @@ -109,10 +109,10 @@ ViewDownloads::prev_focus() { // Also add focus thingie here? struct view_downloads_compare : std::binary_function { - view_downloads_compare(const ViewDownloads::sort_list& s) : m_sort(s) {} + view_downloads_compare(const View::sort_list& s) : m_sort(s) {} bool operator () (Download* d1, Download* d2) const { - for (ViewDownloads::sort_list::const_iterator itr = m_sort.begin(), last = m_sort.end(); itr != last; ++itr) + for (View::sort_list::const_iterator itr = m_sort.begin(), last = m_sort.end(); itr != last; ++itr) if ((**itr)(d1, d2)) return true; else if ((**itr)(d2, d1)) @@ -123,14 +123,14 @@ struct view_downloads_compare : std::binary_function return false; } - const ViewDownloads::sort_list& m_sort; + const View::sort_list& m_sort; }; struct view_downloads_filter : std::unary_function { - view_downloads_filter(const ViewDownloads::filter_list& s) : m_filter(s) {} + view_downloads_filter(const View::filter_list& s) : m_filter(s) {} bool operator () (Download* d1) const { - for (ViewDownloads::filter_list::const_iterator itr = m_filter.begin(), last = m_filter.end(); itr != last; ++itr) + for (View::filter_list::const_iterator itr = m_filter.begin(), last = m_filter.end(); itr != last; ++itr) if (!(**itr)(d1)) return false; @@ -139,11 +139,11 @@ struct view_downloads_filter : std::unary_function { return true; } - const ViewDownloads::filter_list& m_filter; + const View::filter_list& m_filter; }; void -ViewDownloads::sort() { +View::sort() { Download* curFocus = focus() != end() ? *focus() : NULL; // Don't go randomly switching around equivalent elements. @@ -154,7 +154,7 @@ ViewDownloads::sort() { } void -ViewDownloads::filter() { +View::filter() { iterator split = std::stable_partition(base_type::begin(), base_type::end(), view_downloads_filter(m_filter)); m_size = position(split); @@ -164,7 +164,7 @@ ViewDownloads::filter() { } void -ViewDownloads::received_insert(core::Download* d) { +View::received_insert(core::Download* d) { // Chagne according to filtered/not. iterator itr; @@ -179,14 +179,14 @@ ViewDownloads::received_insert(core::Download* d) { } if (m_focus > m_size) - throw torrent::internal_error("ViewDownloads::received_insert(...) m_focus > m_size."); + throw torrent::internal_error("View::received_insert(...) m_focus > m_size."); base_type::insert(itr, d); m_signalChanged.emit(); } void -ViewDownloads::received_erase(core::Download* d) { +View::received_erase(core::Download* d) { iterator itr = std::find(begin(), end_filtered(), d); if (itr == end_filtered()) diff --git a/src/core/view_downloads.h b/src/core/view.h similarity index 100% rename from src/core/view_downloads.h rename to src/core/view.h diff --git a/src/core/view_manager.cc b/src/core/view_manager.cc index 32f85560..0731171f 100644 --- a/src/core/view_manager.cc +++ b/src/core/view_manager.cc @@ -43,7 +43,7 @@ #include "globals.h" #include "download.h" -#include "view_downloads.h" +#include "view.h" #include "view_manager.h" namespace core { @@ -123,17 +123,21 @@ ViewManager::ViewManager(DownloadList* dl) : m_sort["stopped"] = new ViewSortVariableValue("state"); m_sort["started"] = new ViewSortReverse(new ViewSortVariableValue("state")); + m_sort["complete"] = new ViewSortVariableValue("complete"); + m_sort["incomplete"] = new ViewSortReverse(new ViewSortVariableValue("complete")); m_sort["state_changed"] = new ViewSortVariableValue("state_changed"); m_sort["state_changed_reverse"] = new ViewSortReverse(new ViewSortVariableValue("state_changed")); m_filter["started"] = new ViewFilterVariableValue("state", 1); m_filter["stopped"] = new ViewFilterVariableValue("state", 0); + m_filter["complete"] = new ViewFilterVariableValue("complete", 1); + m_filter["incomplete"] = new ViewFilterVariableValue("complete", 0); } void ViewManager::clear() { - std::for_each(begin(), end(), rak::call_delete()); + std::for_each(begin(), end(), rak::call_delete()); std::for_each(m_sort.begin(), m_sort.end(), rak::on(rak::mem_ptr_ref(&sort_map::value_type::second), rak::call_delete())); base_type::clear(); @@ -144,7 +148,7 @@ ViewManager::insert(const std::string& name) { if (find(name) != end()) throw torrent::internal_error("ViewManager::insert(...) name already inserted."); - ViewDownloads* view = new ViewDownloads(); + View* view = new View(); view->initialize(name, m_list); return base_type::insert(end(), view); @@ -152,12 +156,12 @@ ViewManager::insert(const std::string& name) { ViewManager::iterator ViewManager::find(const std::string& name) { - return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&ViewDownloads::name))); + return std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name))); } ViewManager::iterator ViewManager::find_throw(const std::string& name) { - iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&ViewDownloads::name))); + iterator itr = std::find_if(begin(), end(), rak::equal(name, std::mem_fun(&View::name))); if (itr == end()) throw torrent::input_error("Could not find view: " + name); @@ -167,7 +171,7 @@ ViewManager::find_throw(const std::string& name) { inline ViewManager::sort_list ViewManager::build_sort_list(const sort_args& args) { - ViewDownloads::sort_list sortList; + View::sort_list sortList; sortList.reserve(args.size()); for (sort_args::const_iterator itr = args.begin(), last = args.end(); itr != last; ++itr) { @@ -211,7 +215,7 @@ ViewManager::set_sort_current(const std::string& name, const sort_args& sort) { inline ViewManager::filter_list ViewManager::build_filter_list(const filter_args& args) { - ViewDownloads::filter_list filterList; + View::filter_list filterList; filterList.reserve(args.size()); for (filter_args::const_iterator itr = args.begin(), last = args.end(); itr != last; ++itr) { diff --git a/src/core/view_manager.h b/src/core/view_manager.h index f841778d..9d49e1d7 100644 --- a/src/core/view_manager.h +++ b/src/core/view_manager.h @@ -41,23 +41,23 @@ #include #include -#include "view_downloads.h" +#include "view.h" namespace core { -class ViewDownloads; +class View; class ViewSort; -class ViewManager : public rak::unordered_vector { +class ViewManager : public rak::unordered_vector { public: - typedef rak::unordered_vector base_type; + typedef rak::unordered_vector base_type; typedef std::map sort_map; - typedef ViewDownloads::sort_list sort_list; + typedef View::sort_list sort_list; typedef std::list sort_args; typedef std::map filter_map; - typedef ViewDownloads::filter_list filter_list; + typedef View::filter_list filter_list; typedef std::list filter_args; using base_type::iterator; @@ -92,8 +92,8 @@ public: iterator find(const std::string& name); iterator find_throw(const std::string& name); - // If ViewDownloads::last_changed() is less than 'timeout' seconds - // ago, don't sort. + // If View::last_changed() is less than 'timeout' seconds ago, don't + // sort. // // Find a better name for 'timeout'. void sort(const std::string& name, uint32_t timeout = 0); diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index 78d36844..266339e8 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -39,7 +39,7 @@ #include #include "core/download.h" -#include "core/view_downloads.h" +#include "core/view.h" #include "canvas.h" #include "globals.h" @@ -53,7 +53,7 @@ WindowDownloadList::~WindowDownloadList() { } void -WindowDownloadList::set_view(core::ViewDownloads* l) { +WindowDownloadList::set_view(core::View* l) { m_view = l; m_connChanged.disconnect(); @@ -76,7 +76,7 @@ WindowDownloadList::redraw() { if (m_view->empty() || m_canvas->get_width() < 5 || m_canvas->get_height() < 2) return; - typedef std::pair Range; + typedef std::pair Range; Range range = rak::advance_bidirectional(m_view->begin(), m_view->focus() != m_view->end() ? m_view->focus() : m_view->begin(), diff --git a/src/display/window_download_list.h b/src/display/window_download_list.h index a6167984..8c22ad17 100644 --- a/src/display/window_download_list.h +++ b/src/display/window_download_list.h @@ -44,7 +44,7 @@ #include "core/download_list.h" namespace core { - class ViewDownloads; + class View; } namespace display { @@ -56,12 +56,12 @@ public: virtual void redraw(); - void set_view(core::ViewDownloads* l); + void set_view(core::View* l); private: - core::ViewDownloads* m_view; + core::View* m_view; - sigc::connection m_connChanged; + sigc::connection m_connChanged; }; } diff --git a/src/main.cc b/src/main.cc index 3e30f0e9..1a47ad92 100644 --- a/src/main.cc +++ b/src/main.cc @@ -162,9 +162,14 @@ main(int argc, char** argv) { // torrent::ConnectionManager* is valid etc. initialize_option_handler(control); + // Currently not doing any sorting on main. control->variable()->process_command("view_add = main"); - control->variable()->process_command("view_sort_new = main,name"); - control->variable()->process_command("view_sort_current = main,name"); + control->variable()->process_command("view_sort_new = main"); + control->variable()->process_command("view_sort_current = main"); + + control->variable()->process_command("view_add = name"); + control->variable()->process_command("view_sort_new = name,name"); + control->variable()->process_command("view_sort_current = name,name"); control->variable()->process_command("view_add = started"); control->variable()->process_command("view_filter = started,started"); @@ -176,15 +181,22 @@ main(int argc, char** argv) { control->variable()->process_command("view_sort_new = stopped,name"); control->variable()->process_command("view_sort_current = stopped,name"); - control->variable()->process_command("view_add = finished"); - //control->variable()->process_command("view_filter = finished,stopped"); - control->variable()->process_command("view_sort_new = finished,state_changed"); - control->variable()->process_command("view_sort_current = finished,state_changed_reverse"); + control->variable()->process_command("view_add = complete"); + control->variable()->process_command("view_filter = complete,complete"); + control->variable()->process_command("view_sort_new = complete,state_changed"); + control->variable()->process_command("view_sort_current = complete,state_changed_reverse"); - control->variable()->process_command("schedule = view_main,10,10,view_sort=main,30"); - control->variable()->process_command("schedule = view_started,10,10,view_sort=started"); - control->variable()->process_command("schedule = view_stopped,10,10,view_sort=stopped"); - control->variable()->process_command("schedule = view_finished,10,10,view_sort=finished,30"); + control->variable()->process_command("view_add = incomplete"); + control->variable()->process_command("view_filter = incomplete,incomplete"); + control->variable()->process_command("view_sort_new = incomplete,state_changed"); + control->variable()->process_command("view_sort_current = incomplete,state_changed_reverse"); + + control->variable()->process_command("schedule = view_main,10,10,view_sort=main,20"); + control->variable()->process_command("schedule = view_name,10,10,view_sort=main,20"); + control->variable()->process_command("schedule = view_started,10,10,view_sort=started,20"); + control->variable()->process_command("schedule = view_stopped,10,10,view_sort=stopped,20"); + control->variable()->process_command("schedule = view_complete,10,10,view_sort=complete,20"); + control->variable()->process_command("schedule = view_incomplete,10,10,view_sort=incomplete,20"); //control->variable()->process_command("schedule = scheduler,10,10,download_scheduler="); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 34ff254a..29260878 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -98,17 +98,17 @@ apply_load_start(Control* m, const std::string& arg) { void apply_stop_untied(Control* m, __UNUSED const std::string& arg) { - core::Manager::DListItr itr = m->core()->download_list().begin(); + core::Manager::DListItr itr = m->core()->download_list()->begin(); - while ((itr = std::find_if(itr, m->core()->download_list().end(), + while ((itr = std::find_if(itr, m->core()->download_list()->end(), rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"), std::not1(std::mem_fun_ref(&std::string::empty))))) - != m->core()->download_list().end()) { + != m->core()->download_list()->end()) { rak::file_stat fs; if (!fs.update(rak::path_expand((*itr)->variable_string("tied_to_file")))) { (*itr)->variable()->set("tied_to_file", std::string()); - m->core()->download_list().stop(*itr); + m->core()->download_list()->stop(*itr); } ++itr; @@ -117,18 +117,18 @@ apply_stop_untied(Control* m, __UNUSED const std::string& arg) { void apply_remove_untied(Control* m, __UNUSED const std::string& arg) { - core::Manager::DListItr itr = m->core()->download_list().begin(); + core::Manager::DListItr itr = m->core()->download_list()->begin(); - while ((itr = std::find_if(itr, m->core()->download_list().end(), + while ((itr = std::find_if(itr, m->core()->download_list()->end(), rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"), std::not1(std::mem_fun_ref(&std::string::empty))))) - != m->core()->download_list().end()) { + != m->core()->download_list()->end()) { rak::file_stat fs; if (!fs.update(rak::path_expand((*itr)->variable_string("tied_to_file")))) { (*itr)->variable()->set("tied_to_file", std::string()); - m->core()->download_list().stop(*itr); - itr = m->core()->download_list().erase(itr); + m->core()->download_list()->stop(*itr); + itr = m->core()->download_list()->erase(itr); } else { ++itr; @@ -145,7 +145,7 @@ void apply_enable_trackers(Control* m, __UNUSED const std::string& arg) { bool state = (arg != "no"); - for (core::Manager::DListItr itr = m->core()->download_list().begin(), last = m->core()->download_list().end(); itr != last; ++itr) { + for (core::Manager::DListItr itr = m->core()->download_list()->begin(), last = m->core()->download_list()->end(); itr != last; ++itr) { torrent::TrackerList tl = (*itr)->download()->tracker_list(); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 67d41110..309423d1 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -47,7 +47,7 @@ #include "core/download.h" #include "core/download_list.h" #include "core/manager.h" -#include "core/view_downloads.h" +#include "core/view.h" #include "core/view_manager.h" #include "input/bindings.h" @@ -130,7 +130,7 @@ DownloadList::activate() { m_control->input()->push_front(m_bindings); - m_control->core()->download_list().slot_map_erase()["0_download_list"] = sigc::mem_fun(this, &DownloadList::receive_download_erased); + m_control->core()->download_list()->slot_map_erase()["0_download_list"] = sigc::mem_fun(this, &DownloadList::receive_download_erased); activate_display(DISPLAY_DOWNLOAD_LIST); } @@ -200,7 +200,8 @@ DownloadList::receive_start_download() { if (m_view->focus() == m_view->end()) return; - m_control->core()->download_list().start(*m_view->focus()); + m_control->core()->download_list()->start(*m_view->focus()); + m_view->set_last_changed(); } void @@ -209,9 +210,11 @@ DownloadList::receive_stop_download() { return; if ((*m_view->focus())->download()->is_active()) - m_control->core()->download_list().stop(*m_view->focus()); + m_control->core()->download_list()->stop(*m_view->focus()); else - m_control->core()->download_list().erase(*m_view->focus()); + m_control->core()->download_list()->erase(*m_view->focus()); + + m_view->set_last_changed(); } void @@ -219,7 +222,8 @@ DownloadList::receive_close_download() { if (m_view->focus() == m_view->end()) return; - m_control->core()->download_list().close(*m_view->focus()); + m_control->core()->download_list()->close(*m_view->focus()); + m_view->set_last_changed(); } void @@ -247,6 +251,7 @@ DownloadList::receive_exit_download() { delete m_uiDownload; m_uiDownload = NULL; + m_view->set_last_changed(); activate(); m_control->display()->adjust_layout(); @@ -273,7 +278,8 @@ DownloadList::receive_check_hash() { if (m_view->focus() == m_view->end()) return; - m_control->core()->check_hash(*m_view->focus()); + // Catch here? + m_control->core()->download_list()->check_hash(*m_view->focus()); } void @@ -419,10 +425,11 @@ DownloadList::setup_keys() { (*m_bindings)['l'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_LOG); (*m_bindings)['1'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "main"); - (*m_bindings)['2'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "started"); - (*m_bindings)['3'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "stopped"); - (*m_bindings)['4'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "finished"); - (*m_bindings)['5'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "incomplete"); + (*m_bindings)['2'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "name"); + (*m_bindings)['3'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "started"); + (*m_bindings)['4'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "stopped"); + (*m_bindings)['5'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "complete"); + (*m_bindings)['6'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "incomplete"); m_uiArray[DISPLAY_LOG]->get_bindings()[' '] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_DOWNLOAD_LIST); } diff --git a/src/ui/download_list.h b/src/ui/download_list.h index ea8139f1..317049fa 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -47,7 +47,7 @@ class Control; namespace core { class Download; - class ViewDownloads; + class View; } namespace input { @@ -159,7 +159,7 @@ private: Download* m_uiDownload; - core::ViewDownloads* m_view; + core::View* m_view; Control* m_control; input::Bindings* m_bindings; diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc index f5659ee8..70f09986 100644 --- a/src/ui/element_download_list.cc +++ b/src/ui/element_download_list.cc @@ -70,7 +70,7 @@ ElementDownloadList::disable(Control* c) { } void -ElementDownloadList::set_view(core::ViewDownloads* l) { +ElementDownloadList::set_view(core::View* l) { m_view = l; if (m_window == NULL) diff --git a/src/ui/element_download_list.h b/src/ui/element_download_list.h index f9672511..41d89ebd 100644 --- a/src/ui/element_download_list.h +++ b/src/ui/element_download_list.h @@ -45,7 +45,7 @@ class Control; namespace core { - class ViewDownloads; + class View; } namespace ui { @@ -59,11 +59,11 @@ public: void activate(Control* c, MItr mItr); void disable(Control* c); - void set_view(core::ViewDownloads* l); + void set_view(core::View* l); private: WDownloadList* m_window; - core::ViewDownloads* m_view; + core::View* m_view; }; }