From 98ad8e87912f662d8fba3f6fdea1f9ae174fa2ca Mon Sep 17 00:00:00 2001 From: rakshasa Date: Thu, 30 Jun 2005 16:42:22 +0000 Subject: [PATCH] Cleaned up ui::Root, fixed updating and hiding status bar. Using displayScheduler for updating windows, much more efficient. Added saving of some parts of the state of torrents. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@482 e378c898-3ddf-0310-93e7-cc216c733640 --- doc/rtorrent.1.xml | 17 +++++++++ doc/rtorrent.rc | 8 +++++ src/core/download.h | 2 ++ src/core/manager.cc | 43 ++++++++++++++++++++-- src/core/manager.h | 5 +++ src/display/manager.cc | 3 +- src/display/window.cc | 21 +++++++++++ src/display/window.h | 46 +++++++++++++----------- src/display/window_download_list.cc | 2 +- src/display/window_download_statusbar.cc | 2 +- src/display/window_file_list.cc | 2 +- src/display/window_http_queue.cc | 2 +- src/display/window_input.cc | 2 -- src/display/window_log.cc | 4 +-- src/display/window_log_complete.cc | 2 -- src/display/window_peer_info.cc | 2 +- src/display/window_peer_list.cc | 2 +- src/display/window_statusbar.cc | 2 +- src/display/window_string_list.cc | 2 -- src/display/window_title.cc | 2 +- src/display/window_tracker_list.cc | 2 +- src/main.cc | 32 ++++++++--------- src/option_handler_rules.cc | 22 +++++++++++- src/option_handler_rules.h | 6 +++- src/ui/control.h | 23 ++++++++---- src/ui/download_list.cc | 13 +++---- src/ui/root.cc | 32 +++++++++-------- src/ui/root.h | 14 ++++---- src/utils/task.h | 1 + 29 files changed, 221 insertions(+), 95 deletions(-) diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml index aa31331b..45d0f0bb 100644 --- a/doc/rtorrent.1.xml +++ b/doc/rtorrent.1.xml @@ -416,6 +416,23 @@ + + hash_interval = ms + + Interval between attempts to check the hash when the chunk + is not in memory, in milliseconds. + + + + + hash_max_tries = tries + + Number of attempts to check the hash while using the mincore + status, before forcing. Overworked systems might need lower + values to get a decent hash checking rate. + + + max_open_files = value diff --git a/doc/rtorrent.rc b/doc/rtorrent.rc index f64d2a22..fff1b9bd 100644 --- a/doc/rtorrent.rc +++ b/doc/rtorrent.rc @@ -53,6 +53,14 @@ # pages in memory thus end up trashing. #hash_read_ahead = 10 +# Interval between attempts to check the hash, in milliseconds. +#hash_interval = 100 + +# Number of attempts to check the hash while using the mincore status, +# before forcing. Overworked systems might need lower values to get a +# decent hash checking rate. +#hash_max_tries = 10 + # Max number of files to keep open simultaniously. #max_open_files = 100 diff --git a/src/core/download.h b/src/core/download.h index 07e93c9e..65811658 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -25,6 +25,7 @@ #include #include +#include namespace core { @@ -38,6 +39,7 @@ public: torrent::Download& get_download() { return m_download; } std::string get_hash() { return m_download.get_hash(); } + torrent::Bencode& get_bencode() { return torrent::download_bencode(m_download.get_hash()); } const std::string& get_message() { return m_message; } diff --git a/src/core/manager.cc b/src/core/manager.cc index 7697483b..03ddbcda 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -31,7 +31,6 @@ #include #include #include -#include #include "download.h" #include "manager.h" @@ -54,8 +53,9 @@ Manager::initialize() { // Register slots to be called when a download is inserted/erased, // opened or closed. + m_downloadList.slot_map_insert().insert("0_initialize_bencode", sigc::mem_fun(*this, &Manager::initialize_bencode)); m_downloadList.slot_map_insert().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().insert("3_manager_start", sigc::mem_fun(*this, &Manager::start)); + m_downloadList.slot_map_insert().insert("3_manager_inserted", sigc::mem_fun(*this, &Manager::receive_download_inserted)); m_downloadList.slot_map_insert().insert("4_store_save", sigc::mem_fun(m_downloadStore, &DownloadStore::save)); m_downloadList.slot_map_erase().insert("1_hash_queue_remove", sigc::mem_fun(m_hashQueue, &HashQueue::remove)); @@ -87,6 +87,16 @@ Manager::cleanup() { core::CurlStack::cleanup(); } +void +Manager::shutdown(bool force) { + if (!force) + std::for_each(m_downloadList.begin(), m_downloadList.end(), + std::bind1st(std::mem_fun(&DownloadList::stop), &m_downloadList)); + else + std::for_each(m_downloadList.begin(), m_downloadList.end(), + std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList)); +} + void Manager::insert(std::string uri) { if (std::strncmp(uri.c_str(), "http://", 7) == 0) { @@ -111,6 +121,8 @@ Manager::erase(DListItr itr) { void Manager::start(Download* d) { try { + d->get_bencode()["rtorrent"]["state"] = "started"; + if (d->get_download().is_active()) return; @@ -132,6 +144,8 @@ Manager::start(Download* d) { void Manager::stop(Download* d) { try { + d->get_bencode()["rtorrent"]["state"] = "stopped"; + m_downloadList.stop(d); } catch (torrent::local_error& e) { @@ -212,6 +226,21 @@ Manager::create_final(std::istream* s) { } } +void +Manager::initialize_bencode(Download* d) { + torrent::Bencode& bencode = d->get_bencode(); + + // TODO: Check that stuff are the right type, like state etc. + if (bencode.has_key("rtorrent") && + bencode["rtorrent"].is_map() && + bencode["rtorrent"].has_key("state") && + bencode["rtorrent"]["state"].is_string()) + return; + + bencode.insert_key("rtorrent", torrent::Bencode(torrent::Bencode::TYPE_MAP)); + bencode["rtorrent"].insert_key("state", "started"); +} + void Manager::prepare_hash_check(Download* d) { m_downloadList.close(d); @@ -242,4 +271,14 @@ Manager::receive_download_done_hash_checked(Download* d) { d->get_download().tracker_send_completed(); } +void +Manager::receive_download_inserted(Download* d) { + // Check if there is an "rtorrent" section in the bencoded data. + + torrent::Bencode& bencode = d->get_bencode(); + + if (bencode["rtorrent"]["state"].as_string() == "started") + start(d); +} + } diff --git a/src/core/manager.h b/src/core/manager.h index cd0532c1..d351351e 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -61,6 +61,8 @@ public: void initialize(); void cleanup(); + void shutdown(bool force); + void insert(std::string uri); DListItr erase(DListItr itr); @@ -77,10 +79,13 @@ private: void create_http(const std::string& uri); void create_final(std::istream* s); + 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); DownloadList m_downloadList; DownloadStore m_downloadStore; diff --git a/src/display/manager.cc b/src/display/manager.cc index 9baf3fce..bd8bd4f1 100644 --- a/src/display/manager.cc +++ b/src/display/manager.cc @@ -83,8 +83,7 @@ void Manager::do_update() { Canvas::refresh_std(); - std::for_each(begin(), end(), rak::if_then(std::mem_fun(&Window::is_active), rak::if_then(std::mem_fun(&Window::is_dirty), - std::mem_fun(&Window::redraw)))); + utils::displayScheduler.execute(utils::Timer::cache()); std::for_each(begin(), end(), rak::if_then(std::mem_fun(&Window::is_active), std::mem_fun(&Window::refresh))); Canvas::do_update(); diff --git a/src/display/window.cc b/src/display/window.cc index fd8a0172..5b54ef8e 100644 --- a/src/display/window.cc +++ b/src/display/window.cc @@ -30,10 +30,31 @@ namespace display { Window::Slot Window::m_slotAdjust; +Window::Window(Canvas* c, bool d, int h) : + m_canvas(c), + m_active(true), + m_dynamic(d), + m_minHeight(h) { + + m_taskUpdate.set_iterator(utils::displayScheduler.end()); + m_taskUpdate.set_slot(sigc::mem_fun(*this, &Window::redraw)); +} + Window::~Window() { + utils::displayScheduler.erase(&m_taskUpdate); delete m_canvas; } +void +Window::set_active(bool a) { + if (a) + mark_dirty(); + else + utils::displayScheduler.erase(&m_taskUpdate); + + m_active = a; +} + void Window::resize(int x, int y, int w, int h) { if (x < 0 || y < 0) diff --git a/src/display/window.h b/src/display/window.h index 00971103..0d368f1b 100644 --- a/src/display/window.h +++ b/src/display/window.h @@ -26,6 +26,7 @@ #include #include "canvas.h" +#include "utils/task.h" #include "utils/timer.h" namespace display { @@ -36,46 +37,51 @@ class Window { public: typedef sigc::slot0 Slot; - Window(Canvas* c = NULL, bool d = false, int h = 1) : - m_canvas(c), m_active(true), m_dynamic(d), m_minHeight(h) {} + Window(Canvas* c = NULL, bool d = false, int h = 1); virtual ~Window(); - bool is_active() { return m_active; } - bool is_dynamic() { return m_dynamic; } - bool is_dirty() { return m_nextDraw <= utils::Timer::cache(); } + bool is_active() { return m_active; } + bool is_dynamic() { return m_dynamic; } + bool is_dirty() { return utils::displayScheduler.is_scheduled(&m_taskUpdate); } - utils::Timer get_next_draw() { return m_nextDraw; } + //utils::Timer get_next_draw() { return m_nextDraw; } - int get_min_height() { return m_minHeight; } + int get_min_height() { return m_minHeight; } - bool get_active() { return m_active; } - void set_active(bool a) { m_active = a; } + bool get_active() { return m_active; } + void set_active(bool a); - void refresh() { m_canvas->refresh(); } - void resize(int x, int y, int w, int h); + void refresh() { m_canvas->refresh(); } + void resize(int x, int y, int w, int h); - void mark_dirty() { m_nextDraw = utils::Timer::min(); } + void mark_dirty(); - virtual void redraw() = 0; + virtual void redraw() = 0; - static void slot_adjust(Slot s) { m_slotAdjust = s; } + static void slot_adjust(Slot s) { m_slotAdjust = s; } protected: Window(const Window&); void operator = (const Window&); - static Slot m_slotAdjust; + static Slot m_slotAdjust; - Canvas* m_canvas; + Canvas* m_canvas; - bool m_active; - bool m_dynamic; - int m_minHeight; + bool m_active; + bool m_dynamic; + int m_minHeight; - utils::Timer m_nextDraw; + utils::TaskItem m_taskUpdate; }; +inline void +Window::mark_dirty() { + utils::displayScheduler.erase(&m_taskUpdate); + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache()); +} + } #endif diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index dab07994..7df3e1c7 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -44,7 +44,7 @@ WindowDownloadList::~WindowDownloadList() { void WindowDownloadList::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); diff --git a/src/display/window_download_statusbar.cc b/src/display/window_download_statusbar.cc index 98267567..83ca9f7e 100644 --- a/src/display/window_download_statusbar.cc +++ b/src/display/window_download_statusbar.cc @@ -37,7 +37,7 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) : void WindowDownloadStatusbar::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index 80c14dcf..8220e84b 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -39,7 +39,7 @@ WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) : void WindowFileList::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 10 * 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 10 * 1000000); m_canvas->erase(); if (m_download->get_download().get_entry_size() == 0 || diff --git a/src/display/window_http_queue.cc b/src/display/window_http_queue.cc index 5ef8d9a8..6b8a5eec 100644 --- a/src/display/window_http_queue.cc +++ b/src/display/window_http_queue.cc @@ -44,7 +44,7 @@ WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) : void WindowHttpQueue::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); cleanup_list(); diff --git a/src/display/window_input.cc b/src/display/window_input.cc index 8af55706..f7ff0b4a 100644 --- a/src/display/window_input.cc +++ b/src/display/window_input.cc @@ -37,9 +37,7 @@ WindowInput::WindowInput(input::TextInput* input) : void WindowInput::redraw() { - m_nextDraw = utils::Timer::max(); m_canvas->erase(); - m_canvas->print(0, 0, "> %s", m_input->c_str()); if (m_focus) diff --git a/src/display/window_log.cc b/src/display/window_log.cc index 99367dec..0651df46 100644 --- a/src/display/window_log.cc +++ b/src/display/window_log.cc @@ -34,7 +34,7 @@ WindowLog::WindowLog(core::Log* l) : Window(new Canvas, false, 0), m_log(l) { - set_active(false); + m_active = false; // We're trying out scheduled tasks instead. m_connUpdate = l->signal_update().connect(sigc::mem_fun(*this, &WindowLog::receive_update)); @@ -51,8 +51,6 @@ WindowLog::find_older() { void WindowLog::redraw() { - m_nextDraw = utils::Timer::max(); - m_canvas->erase(); int pos = 0; diff --git a/src/display/window_log_complete.cc b/src/display/window_log_complete.cc index ec3e202f..faf7f1e0 100644 --- a/src/display/window_log_complete.cc +++ b/src/display/window_log_complete.cc @@ -49,8 +49,6 @@ WindowLogComplete::find_older() { void WindowLogComplete::redraw() { - m_nextDraw = utils::Timer::max(); - m_canvas->erase(); int pos = 0; diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index 91dfb227..1c92b20c 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -42,7 +42,7 @@ WindowPeerInfo::WindowPeerInfo(core::Download* d, PList* l, PList::iterator* f) void WindowPeerInfo::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); int y = 0; diff --git a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc index 1e734d44..607e55e9 100644 --- a/src/display/window_peer_list.cc +++ b/src/display/window_peer_list.cc @@ -41,7 +41,7 @@ WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) void WindowPeerList::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); int x = 2; diff --git a/src/display/window_statusbar.cc b/src/display/window_statusbar.cc index 7bcf91ad..e9e0c547 100644 --- a/src/display/window_statusbar.cc +++ b/src/display/window_statusbar.cc @@ -39,7 +39,7 @@ WindowStatusbar::WindowStatusbar(core::Manager* c) : void WindowStatusbar::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); diff --git a/src/display/window_string_list.cc b/src/display/window_string_list.cc index b7c427ff..8b5d81df 100644 --- a/src/display/window_string_list.cc +++ b/src/display/window_string_list.cc @@ -37,8 +37,6 @@ WindowStringList::~WindowStringList() { void WindowStringList::redraw() { - m_nextDraw = utils::Timer::max(); - m_canvas->erase(); size_t ypos = 0; diff --git a/src/display/window_title.cc b/src/display/window_title.cc index a865ce23..3037f722 100644 --- a/src/display/window_title.cc +++ b/src/display/window_title.cc @@ -34,7 +34,7 @@ WindowTitle::WindowTitle(const std::string& s) : void WindowTitle::redraw() { - m_nextDraw = utils::Timer::cache().round_seconds() + 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000); m_canvas->erase(); m_canvas->print(std::max(0, (m_canvas->get_width() - (int)m_title.size()) / 2 - 4), 0, diff --git a/src/display/window_tracker_list.cc b/src/display/window_tracker_list.cc index b03a1fd7..baaf2916 100644 --- a/src/display/window_tracker_list.cc +++ b/src/display/window_tracker_list.cc @@ -41,7 +41,7 @@ WindowTrackerList::WindowTrackerList(core::Download* d, unsigned int* focus) : void WindowTrackerList::redraw() { // TODO: Make this depend on tracker signal. - m_nextDraw = utils::Timer::cache().round_seconds() + 10 * 1000000; + utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 10 * 1000000); m_canvas->erase(); int pos = 0; diff --git a/src/main.cc b/src/main.cc index da25deca..55da4e48 100644 --- a/src/main.cc +++ b/src/main.cc @@ -42,7 +42,6 @@ #include "display/canvas.h" #include "display/window.h" #include "ui/control.h" -#include "ui/root.h" #include "input/bindings.h" #include "utils/task.h" @@ -64,6 +63,7 @@ void print_help(); namespace utils { TaskScheduler taskScheduler; + TaskScheduler displayScheduler; } bool @@ -85,15 +85,12 @@ do_shutdown(ui::Control* c) { is_shutting_down = true; torrent::listen_close(); - - std::for_each(c->get_core().get_download_list().begin(), c->get_core().get_download_list().end(), - std::bind1st(std::mem_fun(&core::Manager::stop), &c->get_core())); + c->get_core().shutdown(false); } else { // Close all torrents, this will stop all tracker connections and cause // a quick shutdown. - std::for_each(c->get_core().get_download_list().begin(), c->get_core().get_download_list().end(), - std::mem_fun(&core::Download::call)); + c->get_core().shutdown(true); } } @@ -132,7 +129,9 @@ initialize_option_handler(ui::Control* c, OptionHandler* optionHandler) { optionHandler->insert("check_hash", new OptionHandlerString(c, &apply_check_hash, &validate_yes_no)); optionHandler->insert("directory", new OptionHandlerString(c, &apply_download_directory, &validate_directory)); - optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_read_ahead)); + optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_hash_read_ahead)); + optionHandler->insert("hash_interval", new OptionHandlerInt(c, &apply_hash_interval, &validate_hash_interval)); + optionHandler->insert("hash_max_tries", new OptionHandlerInt(c, &apply_hash_max_tries, &validate_hash_max_tries)); optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files, &validate_fd)); optionHandler->insert("throttle_interval", new OptionHandlerInt(c, &apply_throttle_interval, &validate_throttle_interval)); @@ -186,7 +185,6 @@ int main(int argc, char** argv) { OptionHandler optionHandler; ui::Control uiControl; - ui::Root uiRoot(&uiControl); utils::Timer::update(); @@ -198,10 +196,10 @@ main(int argc, char** argv) { try { SignalHandler::set_ignore(SIGPIPE); - SignalHandler::set_handler(SIGINT, sigc::bind(sigc::mem_fun(uiRoot, &ui::Root::set_shutdown_received), true)); + SignalHandler::set_handler(SIGINT, sigc::bind(sigc::mem_fun(uiControl, &ui::Control::set_shutdown_received), true)); SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV)); - SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); - SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE)); + SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); + SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE)); // Need to initialize this before parseing options. torrent::initialize(); @@ -214,7 +212,7 @@ main(int argc, char** argv) { initialize_display(&uiControl); initialize_core(&uiControl); - uiRoot.init(); + uiControl.get_ui().init(&uiControl); load_session_torrents(&uiControl); load_arg_torrents(&uiControl, argv + firstArg, argv + argc); @@ -223,9 +221,9 @@ main(int argc, char** argv) { while (!is_shutting_down || !torrent::is_inactive()) { - if (uiRoot.get_shutdown_received()) { + if (uiControl.get_shutdown_received()) { do_shutdown(&uiControl); - uiRoot.set_shutdown_received(false); + uiControl.set_shutdown_received(false); } utils::Timer::update(); @@ -233,14 +231,16 @@ main(int argc, char** argv) { // This needs to be called every second or so. Currently done by // the throttle task in libtorrent. - uiControl.get_display().do_update(); + if (!utils::displayScheduler.empty() && + utils::displayScheduler.get_next_timeout() <= utils::Timer::cache()) + uiControl.get_display().do_update(); uiControl.get_core().get_poll().poll(!utils::taskScheduler.empty() ? utils::taskScheduler.get_next_timeout() - utils::Timer::cache() : 60 * 1000000); } - uiRoot.cleanup(); + uiControl.get_ui().cleanup(); uiControl.get_core().cleanup(); display::Canvas::erase_std(); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index e41c48b6..e0e84e8d 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -71,10 +71,20 @@ validate_rate(int arg) { } bool -validate_read_ahead(int arg) { +validate_hash_read_ahead(int arg) { return arg >= 1 && arg < 64; } +bool +validate_hash_interval(int arg) { + return arg >= 1 && arg < 1000; +} + +bool +validate_hash_max_tries(int arg) { + return arg >= 1 && arg < 20; +} + bool validate_fd(int arg) { return arg >= 10 && arg < (1 << 16); @@ -123,6 +133,16 @@ apply_hash_read_ahead(ui::Control* m, int arg) { torrent::set_hash_read_ahead(arg << 20); } +void +apply_hash_interval(ui::Control* m, int arg) { + torrent::set_hash_interval(arg * 1000); +} + +void +apply_hash_max_tries(ui::Control* m, int arg) { + torrent::set_hash_max_tries(arg); +} + void apply_max_open_files(ui::Control* m, int arg) { torrent::set_max_open_files(arg); diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h index 016f162b..67f16365 100644 --- a/src/option_handler_rules.h +++ b/src/option_handler_rules.h @@ -41,7 +41,9 @@ bool validate_yes_no(const std::string& arg); bool validate_download_peers(int arg); bool validate_rate(int arg); -bool validate_read_ahead(int arg); +bool validate_hash_read_ahead(int arg); +bool validate_hash_interval(int arg); +bool validate_hash_max_tries(int arg); bool validate_fd(int arg); bool validate_throttle_interval(int arg); @@ -56,6 +58,8 @@ void apply_global_download_rate(ui::Control* m, int arg); void apply_global_upload_rate(ui::Control* m, int arg); void apply_hash_read_ahead(ui::Control* m, int arg); +void apply_hash_interval(ui::Control* m, int arg); +void apply_hash_max_tries(ui::Control* m, int arg); void apply_max_open_files(ui::Control* m, int arg); void apply_throttle_interval(ui::Control* m, int arg); diff --git a/src/ui/control.h b/src/ui/control.h index 046ccd42..14f6187d 100644 --- a/src/ui/control.h +++ b/src/ui/control.h @@ -27,23 +27,32 @@ #include "display/manager.h" #include "input/manager.h" +#include "root.h" + namespace ui { class Control { public: - Control() {} + Control() : m_shutdownReceived(false) {} - core::Manager& get_core() { return m_core; } - display::Manager& get_display() { return m_display; } - input::Manager& get_input() { return m_input; } + bool get_shutdown_received() { return m_shutdownReceived; } + void set_shutdown_received(bool v) { m_shutdownReceived = v; } + + Root& get_ui() { return m_ui; } + core::Manager& get_core() { return m_core; } + display::Manager& get_display() { return m_display; } + input::Manager& get_input() { return m_input; } private: Control(const Control&); void operator = (const Control&); - core::Manager m_core; - display::Manager m_display; - input::Manager m_input; + bool m_shutdownReceived; + + Root m_ui; + core::Manager m_core; + display::Manager m_display; + input::Manager m_input; }; } diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 474a9953..c6ed82d3 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -37,6 +37,7 @@ #include "display/window_input.h" #include "display/window_log.h" #include "display/window_title.h" +#include "display/window_statusbar.h" #include "control.h" #include "download.h" @@ -113,15 +114,15 @@ DownloadList::disable() { if (!is_active()) throw std::logic_error("ui::Download::disable() called on an already disabled object"); - disable_display(); - - utils::taskScheduler.erase(&m_taskUpdate); - if (m_windowTextInput->is_active()) { m_windowTextInput->get_input()->clear(); receive_exit_input(); } + disable_display(); + + utils::taskScheduler.erase(&m_taskUpdate); + m_control->get_display().erase(m_window); m_control->get_display().erase(m_windowTitle); m_control->get_display().erase(m_windowTextInput); @@ -225,7 +226,7 @@ DownloadList::receive_check_hash() { void DownloadList::receive_view_input() { - //m_windowStatus->set_active(false); + m_control->get_ui().window_statusbar()->set_active(false); m_windowTextInput->set_active(true); m_control->get_display().adjust_layout(); @@ -239,7 +240,7 @@ DownloadList::receive_view_input() { void DownloadList::receive_exit_input() { - //m_windowStatus->set_active(true); + m_control->get_ui().window_statusbar()->set_active(true); m_windowTextInput->set_active(false); m_control->get_input().set_text_input(); diff --git a/src/ui/root.cc b/src/ui/root.cc index 4a6e2190..68757700 100644 --- a/src/ui/root.cc +++ b/src/ui/root.cc @@ -34,24 +34,24 @@ namespace ui { -Root::Root(Control* c) : - m_shutdownReceived(false), - m_control(c), +Root::Root() : + m_control(NULL), m_downloadList(NULL), - m_windowStatus(NULL) { + m_windowStatusbar(NULL) { } void -Root::init() { - if (m_downloadList != NULL) +Root::init(Control* c) { + if (m_control != NULL) throw std::logic_error("Root::init() called twice on the same object"); + m_control = c; setup_keys(); - m_windowStatus = new WStatus(&m_control->get_core()); - m_downloadList = new DownloadList(m_control); + m_windowStatusbar = new WStatusbar(&m_control->get_core()); + m_downloadList = new DownloadList(m_control); - m_control->get_display().push_back(m_windowStatus); + m_control->get_display().push_back(m_windowStatusbar); m_downloadList->activate(); m_downloadList->slot_open_uri(sigc::mem_fun(m_control->get_core(), &core::Manager::insert)); @@ -59,15 +59,19 @@ Root::init() { void Root::cleanup() { + if (m_control == NULL) + throw std::logic_error("Root::cleanup() called twice on the same object"); + if (m_downloadList->is_active()) m_downloadList->disable(); - m_control->get_display().erase(m_windowStatus); + m_control->get_display().erase(m_windowStatusbar); delete m_downloadList; - delete m_windowStatus; + delete m_windowStatusbar; m_control->get_input().erase(&m_bindings); + m_control = NULL; } void @@ -89,19 +93,19 @@ Root::setup_keys() { m_bindings['C'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_read_throttle), -50); m_bindings[KEY_RESIZE] = sigc::mem_fun(m_control->get_display(), &display::Manager::adjust_layout); - m_bindings['\x11'] = sigc::bind(sigc::mem_fun(*this, &Root::set_shutdown_received), true); + m_bindings['\x11'] = sigc::bind(sigc::mem_fun(*m_control, &Control::set_shutdown_received), true); } void Root::receive_read_throttle(int t) { - //m_downloadList->mark_dirty(); + m_windowStatusbar->mark_dirty(); torrent::set_read_throttle(torrent::get_read_throttle() + t * 1024); } void Root::receive_write_throttle(int t) { - //m_downloadList->mark_dirty(); + m_windowStatusbar->mark_dirty(); torrent::set_write_throttle(torrent::get_write_throttle() + t * 1024); } diff --git a/src/ui/root.h b/src/ui/root.h index 5736ce38..d6fe4d48 100644 --- a/src/ui/root.h +++ b/src/ui/root.h @@ -32,18 +32,18 @@ namespace display { namespace ui { class DownloadList; +class Control; class Root { public: - typedef display::WindowStatusbar WStatus; + typedef display::WindowStatusbar WStatusbar; - Root(Control* c); + Root(); - void init(); + void init(Control* c); void cleanup(); - bool get_shutdown_received() { return m_shutdownReceived; } - void set_shutdown_received(bool v) { m_shutdownReceived = v; } + WStatusbar* window_statusbar() { return m_windowStatusbar; } private: void setup_keys(); @@ -51,12 +51,10 @@ private: void receive_read_throttle(int t); void receive_write_throttle(int t); - bool m_shutdownReceived; - Control* m_control; DownloadList* m_downloadList; - WStatus* m_windowStatus; + WStatusbar* m_windowStatusbar; input::Bindings m_bindings; }; diff --git a/src/utils/task.h b/src/utils/task.h index 366ba11d..2f468c2e 100644 --- a/src/utils/task.h +++ b/src/utils/task.h @@ -28,6 +28,7 @@ namespace utils { extern TaskScheduler taskScheduler; +extern TaskScheduler displayScheduler; }