diff --git a/src/core/download.h b/src/core/download.h index a466b454..b6b29878 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -8,6 +8,9 @@ namespace core { class Download { public: + bool is_open() { return m_download.is_open(); } + bool is_done() { return m_download.get_chunks_done() == m_download.get_chunks_total(); } + void set_download(torrent::Download d); void release_download(); diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index 17902f74..5ff2c26f 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -1,6 +1,7 @@ #include "config.h" #include "core/download.h" +#include "utils/algorithm.h" #include "canvas.h" #include "utils.h" @@ -23,56 +24,49 @@ WindowDownloadList::redraw() { if (m_list->empty()) return; - DList::iterator itr, last; - - int pos = 0, y = 0; + typedef std::pair Range; - if (*m_focus != m_list->end()) { - int i = 0; - itr = last = *m_focus; - - while (i < m_canvas->get_height() - y - 3 && !(itr == m_list->begin() && last == m_list->end())) { - if (last != m_list->end()) { - ++last; - i += 3; - } + Range range = utils::iterate_both_distance(m_list->begin(), + *m_focus != m_list->end() ? *m_focus : m_list->begin(), + m_list->end(), + m_canvas->get_height() / 3); - if (itr != m_list->begin() && i < m_canvas->get_height() - y - 3) { - --itr; - i += 3; - } - } + // Make sure we properly fill out the last lines so it looks like + // there are more torrents, yet don't hide it if we got the last one + // in focus. + if (range.second != m_list->end()) + ++range.second; - } else { - itr = m_list->begin(); - last = m_list->end(); - } + int pos = 0; + + while (range.first != range.second) { + torrent::Download& d = (*range.first)->get_download(); - while (itr != m_list->end() && y < m_canvas->get_height()) { m_canvas->print(0, pos++, "%c %s", - itr == *m_focus ? '*' : ' ', - (*itr)->get_download().get_name().c_str()); + range.first == *m_focus ? '*' : ' ', + d.get_name().c_str()); - if ((*itr)->get_download().get_chunks_done() != (*itr)->get_download().get_chunks_total() || !(*itr)->get_download().is_open()) - m_canvas->print(0, pos++, "%c Torrent: %.1f / %.1f MiB Rate:%5.1f /%5.1f KiB Uploaded: %.1f MiB", - itr == *m_focus ? '*' : ' ', - (double)(*itr)->get_download().get_bytes_done() / (double)(1 << 20), - (double)(*itr)->get_download().get_bytes_total() / (double)(1 << 20), - (double)(*itr)->get_download().get_rate_up() / 1024.0, - (double)(*itr)->get_download().get_rate_down() / 1024.0, - (double)(*itr)->get_download().get_bytes_up() / (double)(1 << 20)); - - else + if ((*range.first)->is_open() && (*range.first)->is_done()) m_canvas->print(0, pos++, "%c Torrent: Done %.1f MiB Rate:%5.1f /%5.1f KiB Uploaded: %.1f MiB", - itr == *m_focus ? '*' : ' ', - (double)(*itr)->get_download().get_bytes_total() / (double)(1 << 20), - (double)(*itr)->get_download().get_rate_up() / 1024.0, - (double)(*itr)->get_download().get_rate_down() / 1024.0, - (double)(*itr)->get_download().get_bytes_up() / (double)(1 << 20)); + range.first == *m_focus ? '*' : ' ', + (double)d.get_bytes_total() / (double)(1 << 20), + (double)d.get_rate_up() / 1024.0, + (double)d.get_rate_down() / 1024.0, + (double)d.get_bytes_up() / (double)(1 << 20)); + else + m_canvas->print(0, pos++, "%c Torrent: %.1f / %.1f MiB Rate:%5.1f /%5.1f KiB Uploaded: %.1f MiB", + range.first == *m_focus ? '*' : ' ', + (double)d.get_bytes_done() / (double)(1 << 20), + (double)d.get_bytes_total() / (double)(1 << 20), + (double)d.get_rate_up() / 1024.0, + (double)d.get_rate_down() / 1024.0, + (double)d.get_bytes_up() / (double)(1 << 20)); - m_canvas->print(0, pos++, "%c %s", itr == *m_focus ? '*' : ' ', print_download_status(*itr).c_str()); + m_canvas->print(0, pos++, "%c %s", + range.first == *m_focus ? '*' : ' ', + print_download_status(*range.first).c_str()); - ++itr; + ++range.first; } } diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index 0e017fad..8a906d67 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -1,6 +1,9 @@ #include "config.h" +#include + #include "core/download.h" +#include "utils/algorithm.h" #include "window_file_list.h" @@ -17,21 +20,28 @@ WindowFileList::redraw() { m_nextDraw = utils::Timer::cache().round_seconds() + 10 * 1000000; m_canvas->erase(); - int y1 = 0; - int y2 = m_canvas->get_height(); + int pos = 0; - m_canvas->print( 2, y1, "File"); - m_canvas->print(55, y1, "Size"); - m_canvas->print(62, y1, "Pri"); - m_canvas->print(67, y1, "Cmpl"); + m_canvas->print( 2, pos, "File"); + m_canvas->print(55, pos, "Size"); + m_canvas->print(62, pos, "Pri"); + m_canvas->print(67, pos, "Cmpl"); - ++y1; + ++pos; - unsigned int files = m_download->get_download().get_entry_size(); - unsigned int index = std::min(std::max((int)*m_focus - (y2 - y1) / 2, 0), (int)files - (y2 - y1)); + if (m_download->get_download().get_entry_size() == 0) + return; - while (index < files && y1 < y2) { - torrent::Entry e = m_download->get_download().get_entry(index); + if (*m_focus >= m_download->get_download().get_entry_size()) + throw std::logic_error("WindowFileList::redraw() called on an object with a bad focus value"); + + typedef std::pair Range; + + Range range = utils::iterate_both_distance(0, *m_focus, m_download->get_download().get_entry_size(), + m_canvas->get_height()); + + while (range.first != range.second) { + torrent::Entry e = m_download->get_download().get_entry(range.first); std::string path = e.get_path(); @@ -60,15 +70,15 @@ WindowFileList::redraw() { break; }; - m_canvas->print(0, y1, "%c %s %5.1f %s %3d", - index == *m_focus ? '*' : ' ', + m_canvas->print(0, pos, "%c %s %5.1f %s %3d", + range.first == *m_focus ? '*' : ' ', path.c_str(), (double)e.get_size() / (double)(1 << 20), priority.c_str(), done_percentage(e)); - ++index; - ++y1; + ++range.first; + ++pos; } } diff --git a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc index fa551a77..d16c93ec 100644 --- a/src/display/window_peer_list.cc +++ b/src/display/window_peer_list.cc @@ -40,79 +40,61 @@ WindowPeerList::redraw() { if (m_list->empty()) return; - PList::iterator itr, last; - - if (*m_focus != m_list->end()) { - int i = 0; - itr = last = *m_focus; - - while (i < m_canvas->get_height() - y && !(itr == m_list->begin() && last == m_list->end())) { - if (itr != m_list->begin()) { - --itr; - ++i; - } - - if (last != m_list->end() && i < m_canvas->get_height() - y) { - ++last; - ++i; - } - } + typedef std::pair Range; - } else { - itr = m_list->begin(); - last = m_list->end(); - } + Range range = utils::iterate_both_distance(m_list->begin(), + *m_focus != m_list->end() ? *m_focus : m_list->begin(), + m_list->end(), + m_canvas->get_height() - y); if (m_download->get_download().get_chunks_total() <= 0) throw std::logic_error("WindowPeerList::redraw() m_slotChunksTotal() returned invalid value"); - while (itr != m_list->end() && y < m_canvas->get_height()) { + while (range.first != range.second) { + torrent::Peer& p = *range.first; + x = 0; m_canvas->print(x, y, "%c %s", - itr == *m_focus ? '*' : ' ', - itr->get_dns().c_str()); + range.first == *m_focus ? '*' : ' ', + p.get_dns().c_str()); x += 18; - m_canvas->print(x, y, "%.1f", - (double)itr->get_rate_up() / 1024); + m_canvas->print(x, y, "%.1f", (double)p.get_rate_up() / 1024); x += 7; - m_canvas->print(x, y, "%.1f", - (double)itr->get_rate_down() / 1024); + m_canvas->print(x, y, "%.1f", (double)p.get_rate_down() / 1024); x += 7; - m_canvas->print(x, y, "%.1f", - (double)itr->get_rate_peer() / 1024); + m_canvas->print(x, y, "%.1f", (double)p.get_rate_peer() / 1024); x += 7; m_canvas->print(x, y, "%c%c/%c%c%c", - itr->get_remote_choked() ? 'c' : 'u', - itr->get_remote_interested() ? 'i' : 'n', - itr->get_local_choked() ? 'c' : 'u', - itr->get_local_interested() ? 'i' : 'n', - itr->get_choke_delayed() ? 'd' : ' '); + p.get_remote_choked() ? 'c' : 'u', + p.get_remote_interested() ? 'i' : 'n', + p.get_local_choked() ? 'c' : 'u', + p.get_local_interested() ? 'i' : 'n', + p.get_choke_delayed() ? 'd' : ' '); x += 7; m_canvas->print(x, y, "%i/%i", - itr->get_outgoing_queue_size(), - itr->get_incoming_queue_size()); + p.get_outgoing_queue_size(), + p.get_incoming_queue_size()); x += 6; - m_canvas->print(x, y, "%3i", done_percentage(*itr)); + m_canvas->print(x, y, "%3i", done_percentage(*range.first)); x += 6; - if (itr->get_incoming_queue_size()) - m_canvas->print(x, y, "%i", - itr->get_incoming_index(0)); + if (p.get_incoming_queue_size()) + m_canvas->print(x, y, "%i", p.get_incoming_index(0)); x += 6; - if (itr->get_snubbed()) + if (p.get_snubbed()) m_canvas->print(x, y, "*"); ++y; - ++itr; + ++range.first; } } diff --git a/src/main.cc b/src/main.cc index 7e0debf4..372baee2 100644 --- a/src/main.cc +++ b/src/main.cc @@ -191,7 +191,7 @@ do_panic(int signum) { void print_help() { - std::cout << "Rakshasa's Torrent client. " << std::endl; + std::cout << "Rakshasa's BitTorrent client " VERSION "." << std::endl; std::cout << std::endl; std::cout << "All value pairs (f.ex rate and queue size) will be in the UP/DOWN" << std::endl; std::cout << "order. Use the up/down/left/right arrow keys to move between screens." << std::endl; diff --git a/src/utils/algorithm.h b/src/utils/algorithm.h index a540968c..a2202924 100644 --- a/src/utils/algorithm.h +++ b/src/utils/algorithm.h @@ -6,7 +6,8 @@ namespace utils { template -_Function for_each_pre(_InputIter __first, _InputIter __last, _Function __f) { +_Function +for_each_pre(_InputIter __first, _InputIter __last, _Function __f) { _InputIter __tmp; while (__first != __last) { @@ -18,6 +19,40 @@ _Function for_each_pre(_InputIter __first, _InputIter __last, _Function __f) { return __f; } +// Return a range with a distance of no more than __distance and +// between __first and __last, centered on __middle1. +template +std::pair<_InputIter, _InputIter> +iterate_both_distance(_InputIter __first, _InputIter __middle1, _InputIter __last, _Distance __distance) { + _InputIter __middle2 = __middle1; + + do { + if (!__distance) + break; + + if (__middle1 != __first) { + --__middle1; + --__distance; + + } else if (__middle2 == __last) { + break; + } + + if (!__distance) + break; + + if (__middle2 != __last) { + ++__middle2; + --__distance; + + } else if (__middle1 == __first) { + break; + } + } while (true); + + return std::make_pair(__middle1, __middle2); +} + } #endif