From c65b6aa9ff6b7506f43106c6cdab410d913edd35 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Fri, 22 Dec 2006 10:54:39 +0000 Subject: [PATCH] * Added file_path_iterator that allows the client to iterate through FileList in a structured manner. Messed up the file list view to test it. * Added operator[] and at(...) to torrent::FileList and torrent::Path. * Fixed Handshake::fill_read_buffer(...) that was throwing due to a bad error check. Patch by Josef Drexler. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@830 e378c898-3ddf-0310-93e7-cc216c733640 --- src/display/window_download_chunks_seen.h | 2 +- src/display/window_file_list.cc | 156 ++++++++++++++++------ src/display/window_file_list.h | 2 - src/ui/element_chunks_seen.cc | 18 +-- 4 files changed, 127 insertions(+), 51 deletions(-) diff --git a/src/display/window_download_chunks_seen.h b/src/display/window_download_chunks_seen.h index 1f877605..9b5d2727 100644 --- a/src/display/window_download_chunks_seen.h +++ b/src/display/window_download_chunks_seen.h @@ -56,7 +56,7 @@ public: unsigned int rows() const; unsigned int chunks_per_row() const { return (width() - 6) / 11 * 10; } - unsigned int max_focus() const { return std::max(rows() - height() + 1, 0); } + unsigned int max_focus() const { return std::max(rows() - height() / 2 + 1, 0); } private: core::Download* m_download; diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index dd02d8ba..bf542c94 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -71,6 +71,72 @@ hack_wstring(const std::string& src) { } */ +// A special purpose iterator class for iterating through FileList as +// a dired structure. +class file_path_iterator { +public: + typedef torrent::FileList::iterator iterator; + typedef torrent::File& reference; + typedef torrent::File* pointer; + + file_path_iterator() {} + explicit file_path_iterator(iterator pos, uint32_t depth = 0) : m_position(pos), m_depth(depth) {} + + bool is_file() const { return m_depth >= 0 && m_depth + 1 == (int32_t)(*m_position)->path()->size(); } + bool is_empty() const { return (*m_position)->path()->size() == 0; } + + bool is_entering() const { return m_depth >= 0 && m_depth + 1 != (int32_t)(*m_position)->path()->size(); } + bool is_leaving() const { return m_depth < 0; } + + uint32_t depth() const { return std::abs(m_depth); } + + iterator base() const { return m_position; } + + reference operator *() const { return **m_position; } + pointer operator ->() const { return *m_position; } + + file_path_iterator operator ++(); + + friend bool operator == (const file_path_iterator& left, const file_path_iterator& right); + friend bool operator != (const file_path_iterator& left, const file_path_iterator& right); + +private: + iterator m_position; + int32_t m_depth; +}; + +file_path_iterator +file_path_iterator::operator ++() { + int32_t sizePath = (*m_position)->path()->size(); + + if (sizePath == 0) { + m_position++; + return *this; + } + + m_depth++; + + if (m_depth == sizePath) + m_depth = -m_depth + 1; + + if (-m_depth == (int32_t)(*m_position)->match_depth_next()) { + m_depth = -m_depth; + m_position++; + } + + return *this; +} + +bool +operator == (const file_path_iterator& left, const file_path_iterator& right) { + return left.m_position == right.m_position && left.m_depth == right.m_depth; +} + +bool +operator != (const file_path_iterator& left, const file_path_iterator& right) { + return left.m_position != right.m_position || left.m_depth != right.m_depth; +} + void WindowFileList::redraw() { m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(10)).round_seconds()); @@ -81,7 +147,7 @@ WindowFileList::redraw() { if (fl->size_files() == 0 || m_canvas->height() < 2) return; - int pos = 0; + unsigned int pos = 0; m_canvas->print( 2, pos, "File"); m_canvas->print(55, pos, "Size"); @@ -95,57 +161,69 @@ WindowFileList::redraw() { if (*m_focus >= fl->size_files()) throw std::logic_error("WindowFileList::redraw() called on an object with a bad focus value"); - Range range = rak::advance_bidirectional(0, *m_focus, fl->size_files(), m_canvas->height() - pos); + std::pair range = rak::advance_bidirectional(0, *m_focus, fl->size_files(), m_canvas->height() - pos); - while (range.first != range.second) { - torrent::File* e = *(fl->begin() + range.first); + file_path_iterator first(fl->begin() + range.first, (*(fl->begin() + range.first))->match_depth_prev()); + file_path_iterator last(fl->end()); - std::string path = e->path()->as_string(); + while (pos != m_canvas->height() && first != last) { + if (first.is_empty()) { + m_canvas->print(0, pos, "EMPTY"); - if (path.length() <= 50) - path = path + std::string(50 - path.length(), ' '); - else - path = path.substr(0, 50); + } else if (first.is_entering()) { + m_canvas->print(first.depth(), pos, "\\ %s", + first.depth() < first->path()->size() ? first->path()->at(first.depth()).c_str() : "UNKNOWN"); - std::string priority; + } else if (first.is_leaving()) { + m_canvas->print(first.depth(), pos, "/"); - switch (e->priority()) { - case torrent::PRIORITY_OFF: - priority = "off"; - break; + } else if (first.is_file()) { + torrent::File* e = &*first; - case torrent::PRIORITY_NORMAL: - priority = " "; - break; + std::string priority; - case torrent::PRIORITY_HIGH: - priority = "hig"; - break; + switch (e->priority()) { + case torrent::PRIORITY_OFF: + priority = "off"; + break; - default: - priority = "BUG"; - break; - }; + case torrent::PRIORITY_NORMAL: + priority = " "; + break; - m_canvas->print(0, pos, "%c %s %6.1f %s %3d %9s", - range.first == *m_focus ? '*' : ' ', - path.c_str(), - (double)e->size_bytes() / (double)(1 << 20), - priority.c_str(), - done_percentage(e), - e->path()->encoding().c_str()); + case torrent::PRIORITY_HIGH: + priority = "hig"; + break; - m_canvas->print(84, pos, "%i - %i %c%c %u", - e->range().first, - e->range().first != e->range().second ? (e->range().second - 1) : e->range().second, - e->is_created() ? 'E' : 'M', - e->is_correct_size() ? 'C' : 'W', - e->path_match_depth()); + default: + priority = "BUG"; + break; + }; - ++range.first; + m_canvas->print(first.depth(), pos, "| %s", + first.depth() < first->path()->size() ? first->path()->at(first.depth()).c_str() : "UNKNOWN"); + + // %6.1f %s %3d %9s", + // (double)e->size_bytes() / (double)(1 << 20), + // priority.c_str(), + // done_percentage(e), + // e->path()->encoding().c_str()); + + m_canvas->print(104, pos, "%i - %i %c%c %u %u", + e->range().first, + e->range().first != e->range().second ? (e->range().second - 1) : e->range().second, + e->is_created() ? 'E' : 'M', + e->is_correct_size() ? 'C' : 'W', + e->match_depth_prev(), + e->match_depth_next()); + + } else { + m_canvas->print(0, pos, "BORK BORK"); + } + + ++first; ++pos; } - } int diff --git a/src/display/window_file_list.h b/src/display/window_file_list.h index 7e9f2612..e16ba6a6 100644 --- a/src/display/window_file_list.h +++ b/src/display/window_file_list.h @@ -53,8 +53,6 @@ namespace display { class WindowFileList : public Window { public: - typedef std::pair Range; - WindowFileList(core::Download* d, unsigned int* focus); virtual void redraw(); diff --git a/src/ui/element_chunks_seen.cc b/src/ui/element_chunks_seen.cc index 867921f8..c31928a8 100644 --- a/src/ui/element_chunks_seen.cc +++ b/src/ui/element_chunks_seen.cc @@ -54,8 +54,8 @@ ElementChunksSeen::ElementChunksSeen(core::Download* d) : m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); - m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementChunksSeen::receive_next); - m_bindings[KEY_UP] = sigc::mem_fun(*this, &ElementChunksSeen::receive_prev); + m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = sigc::mem_fun(*this, &ElementChunksSeen::receive_next); + m_bindings[KEY_UP] = m_bindings['P' - '@'] = sigc::mem_fun(*this, &ElementChunksSeen::receive_prev); m_bindings[KEY_NPAGE] = sigc::mem_fun(*this, &ElementChunksSeen::receive_pagenext); m_bindings[KEY_PPAGE] = sigc::mem_fun(*this, &ElementChunksSeen::receive_pageprev); } @@ -137,14 +137,14 @@ ElementChunksSeen::receive_pagenext() { throw torrent::internal_error("ui::ElementChunksSeen::receive_pagenext(...) called on a disabled object"); unsigned int visible = m_window->height() - 1; - unsigned int scrollable = std::max(m_window->rows() - visible, 0); + unsigned int maxFocus = m_window->max_focus(); - if (scrollable == 0 || m_focus == scrollable) + if (maxFocus == 0 || m_focus == maxFocus) m_focus = 0; - else if (m_focus + visible / 2 < scrollable) + else if (m_focus + visible / 2 < maxFocus) m_focus += visible / 2; else - m_focus = scrollable; + m_focus = maxFocus; m_window->mark_dirty(); } @@ -155,12 +155,12 @@ ElementChunksSeen::receive_pageprev() { throw torrent::internal_error("ui::ElementChunksSeen::receive_pageprev(...) called on a disabled object"); unsigned int visible = m_window->height() - 1; - unsigned int scrollable = std::max(m_window->rows() - visible, 0); + unsigned int maxFocus = m_window->max_focus(); if (m_focus > visible / 2) m_focus -= visible / 2; - else if (scrollable > 0 && m_focus == 0) - m_focus = scrollable; + else if (maxFocus > 0 && m_focus == 0) + m_focus = maxFocus; else m_focus = 0;