From c453565e8fc48821295441803adaa8f4e97940f9 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Mon, 25 Dec 2006 10:54:31 +0000 Subject: [PATCH] * Added FileListIterator to the API, which allows the client to iterate through FileList as if it consisted of directories. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@831 e378c898-3ddf-0310-93e7-cc216c733640 --- rak/algorithm.h | 24 ++++++++ src/display/window_file_list.cc | 106 +++++++------------------------- src/display/window_file_list.h | 14 +++-- src/ui/element_file_list.cc | 79 ++++++++++-------------- src/ui/element_file_list.h | 5 +- 5 files changed, 91 insertions(+), 137 deletions(-) diff --git a/rak/algorithm.h b/rak/algorithm.h index e8a1f173..4d400f10 100644 --- a/rak/algorithm.h +++ b/rak/algorithm.h @@ -91,6 +91,28 @@ advance_bidirectional(_InputIter __first, _InputIter __middle1, _InputIter __las return std::make_pair(__middle1, __middle2); } +template +_InputIter +advance_forward(_InputIter __first, _InputIter __last, _Distance __distance) { + while (__first != __last && __distance != 0) { + __first++; + __distance--; + } + + return __first; +} + +template +_InputIter +advance_backward(_InputIter __first, _InputIter __last, _Distance __distance) { + while (__first != __last && __distance != 0) { + __first--; + __distance--; + } + + return __first; +} + template struct compare_base : public std::binary_function<_Value, _Value, bool> { bool operator () (const _Value& complete, const _Value& base) const { @@ -133,6 +155,8 @@ make_base(_InputIter __first, _InputIter __last) { return __base; } + + } #endif diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index bf542c94..2e3409d2 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include "core/download.h" @@ -48,7 +49,7 @@ namespace display { -WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) : +WindowFileList::WindowFileList(core::Download* d, iterator* focus) : Window(new Canvas, 0, 0, 0, extent_full, extent_full), m_download(d), m_focus(focus) { @@ -71,72 +72,6 @@ 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()); @@ -158,27 +93,30 @@ WindowFileList::redraw() { ++pos; - if (*m_focus >= fl->size_files()) - throw std::logic_error("WindowFileList::redraw() called on an object with a bad focus value"); +// if (m_focus->first >= fl->size_files() || m_focus->second >= (*(fl->begin() + m_focus->first))->path()->size()) +// throw torrent::internal_error("WindowFileList::redraw() called on an object with a bad focus value."); - std::pair 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); - file_path_iterator first(fl->begin() + range.first, (*(fl->begin() + range.first))->match_depth_prev()); - file_path_iterator last(fl->end()); +// iterator first(fl->begin() + range.first, (*(fl->begin() + range.first))->match_depth_prev()); +// iterator last(fl->end()); - while (pos != m_canvas->height() && first != last) { - if (first.is_empty()) { + std::pair range = + rak::advance_bidirectional(iterator(fl->begin()), *m_focus, iterator(fl->end()), m_canvas->height() - pos); + + while (pos != m_canvas->height() && range.first != range.second) { + if (range.first.is_empty()) { m_canvas->print(0, pos, "EMPTY"); - } 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"); + } else if (range.first.is_entering()) { + m_canvas->print(range.first.depth(), pos, "\\ %s", + range.first.depth() < (*range.first)->path()->size() ? (*range.first)->path()->at(range.first.depth()).c_str() : "UNKNOWN"); - } else if (first.is_leaving()) { - m_canvas->print(first.depth(), pos, "/"); + } else if (range.first.is_leaving()) { + m_canvas->print(range.first.depth(), pos, "/"); - } else if (first.is_file()) { - torrent::File* e = &*first; + } else if (range.first.is_file()) { + torrent::File* e = *range.first; std::string priority; @@ -200,8 +138,8 @@ WindowFileList::redraw() { break; }; - m_canvas->print(first.depth(), pos, "| %s", - first.depth() < first->path()->size() ? first->path()->at(first.depth()).c_str() : "UNKNOWN"); + m_canvas->print(range.first.depth(), pos, "| %s", + range.first.depth() < (*range.first)->path()->size() ? (*range.first)->path()->at(range.first.depth()).c_str() : "UNKNOWN"); // %6.1f %s %3d %9s", // (double)e->size_bytes() / (double)(1 << 20), @@ -221,7 +159,7 @@ WindowFileList::redraw() { m_canvas->print(0, pos, "BORK BORK"); } - ++first; + ++range.first; ++pos; } } diff --git a/src/display/window_file_list.h b/src/display/window_file_list.h index e16ba6a6..72f72573 100644 --- a/src/display/window_file_list.h +++ b/src/display/window_file_list.h @@ -43,6 +43,7 @@ namespace torrent { class File; + class FileListIterator; } namespace core { @@ -53,16 +54,17 @@ namespace display { class WindowFileList : public Window { public: - WindowFileList(core::Download* d, unsigned int* focus); + typedef torrent::FileListIterator iterator; - virtual void redraw(); + WindowFileList(core::Download* d, iterator* focus); + + virtual void redraw(); private: - int done_percentage(torrent::File* e); + int done_percentage(torrent::File* e); - core::Download* m_download; - - unsigned int* m_focus; + core::Download* m_download; + iterator* m_focus; }; } diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc index 342ebda9..8c7c4dc4 100644 --- a/src/ui/element_file_list.cc +++ b/src/ui/element_file_list.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include #include @@ -53,7 +54,7 @@ namespace ui { ElementFileList::ElementFileList(core::Download* d) : m_download(d), m_window(NULL), - m_focus(0) { + m_focus(iterator(d->download()->file_list()->begin())) { m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = sigc::mem_fun(&m_slotExit, &slot_type::operator()); @@ -104,47 +105,38 @@ ElementFileList::window() { void ElementFileList::receive_next() { - if (m_window == NULL) - throw torrent::internal_error("ui::ElementFileList::receive_next(...) called on a disabled object"); + torrent::FileList* fl = m_download->download()->file_list(); - if (++m_focus >= m_download->download()->file_list()->size_files()) - m_focus = 0; + if (m_focus == iterator(fl->end()) || ++m_focus == iterator(fl->end())) + m_focus = iterator(fl->begin()); m_window->mark_dirty(); } void ElementFileList::receive_prev() { - if (m_window == NULL) - throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); - torrent::FileList* fl = m_download->download()->file_list(); - if (fl->size_files() == 0) - return; - - if (m_focus != 0) - --m_focus; - else - m_focus = fl->size_files() - 1; + if (m_focus == iterator(fl->begin())) + m_focus = iterator(fl->end()); + m_focus--; m_window->mark_dirty(); } void ElementFileList::receive_pagenext() { - if (m_window == NULL) - throw torrent::internal_error("ui::ElementFileList::receive_pagenext(...) called on a disabled object"); - - unsigned int count = (m_window->height() - 1) / 2; torrent::FileList* fl = m_download->download()->file_list(); - if (m_focus + count < fl->size_files()) - m_focus += count; - else if (m_focus == fl->size_files() - 1) - m_focus = 0; - else - m_focus = fl->size_files() - 1; + if (m_focus == --iterator(fl->end())) { + m_focus = iterator(fl->begin()); + + } else { + m_focus = rak::advance_forward(m_focus, iterator(fl->end()), (m_window->height() - 1) / 2); + + if (m_focus == iterator(fl->end())) + m_focus = --iterator(fl->end()); + } m_window->mark_dirty(); } @@ -156,17 +148,10 @@ ElementFileList::receive_pageprev() { torrent::FileList* fl = m_download->download()->file_list(); - if (fl->size_files() == 0) - return; - - unsigned int count = (m_window->height() - 1) / 2; - - if (m_focus > count) - m_focus -= count; - else if (m_focus == 0) - m_focus = fl->size_files() - 1; + if (m_focus == iterator(fl->begin())) + m_focus = --iterator(fl->end()); else - m_focus = 0; + m_focus = rak::advance_backward(m_focus, iterator(fl->begin()), (m_window->height() - 1) / 2); m_window->mark_dirty(); } @@ -176,14 +161,16 @@ ElementFileList::receive_priority() { if (m_window == NULL) throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); - torrent::FileList* fl = m_download->download()->file_list(); + // Fix priorities. - if (m_focus >= fl->size_files()) - return; +// torrent::FileList* fl = m_download->download()->file_list(); - torrent::File* file = *(fl->begin() + m_focus); +// if (m_focus >= fl->size_files()) +// return; - file->set_priority(next_priority(file->priority())); +// torrent::File* file = *(fl->begin() + m_focus); + +// file->set_priority(next_priority(file->priority())); m_download->download()->update_priorities(); m_window->mark_dirty(); @@ -194,15 +181,15 @@ ElementFileList::receive_change_all() { if (m_window == NULL) throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); - torrent::FileList* fl = m_download->download()->file_list(); +// torrent::FileList* fl = m_download->download()->file_list(); - if (m_focus >= fl->size_files()) - return; +// if (m_focus >= fl->size_files()) +// return; - Priority p = next_priority((*(fl->begin() + m_focus))->priority()); +// Priority p = next_priority((*(fl->begin() + m_focus))->priority()); - for (torrent::FileList::iterator itr = fl->begin(), last = fl->end(); itr != last; ++itr) - (*itr)->set_priority(p); +// for (torrent::FileList::iterator itr = fl->begin(), last = fl->end(); itr != last; ++itr) +// (*itr)->set_priority(p); m_download->download()->update_priorities(); m_window->mark_dirty(); diff --git a/src/ui/element_file_list.h b/src/ui/element_file_list.h index 66978b60..1333be78 100644 --- a/src/ui/element_file_list.h +++ b/src/ui/element_file_list.h @@ -38,6 +38,7 @@ #define RTORRENT_UI_ELEMENT_FILE_LIST_H #include +#include #include "core/download.h" @@ -56,6 +57,8 @@ public: typedef torrent::priority_t Priority; typedef display::WindowFileList WFileList; + typedef torrent::FileListIterator iterator; + ElementFileList(core::Download* d); void activate(display::Frame* frame, bool focus = true); @@ -78,7 +81,7 @@ private: WFileList* m_window; // Change to unsigned, please. - unsigned int m_focus; + iterator m_focus; }; }