diff --git a/configure.ac b/configure.ac
index 846a01ad..c7329ac8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(rtorrent, 0.7.1, jaris@ifi.uio.no)
+AC_INIT(rtorrent, 0.7.2, jaris@ifi.uio.no)
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
@@ -23,7 +23,7 @@ TORRENT_WITHOUT_NCURSESW()
TORRENT_WITHOUT_STATVFS()
TORRENT_WITHOUT_STATFS()
-PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.11.1,
+PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.11.2,
CXXFLAGS="$CXXFLAGS $STUFF_CFLAGS $CURL_CFLAGS";
LIBS="$LIBS $STUFF_LIBS $CURL_LIBS")
diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml
index 671fa138..6be07fa7 100644
--- a/doc/rtorrent.1.xml
+++ b/doc/rtorrent.1.xml
@@ -221,7 +221,8 @@ Toggle whether torrent ignores ratio settings.
->
View torrent file list. Use the space-bar to change the file priority
-and * to change the priority of all files.
+and * to change the priority of all
+files. Use / to collapse the directories. OUTDATED
diff --git a/src/core/download_list.cc b/src/core/download_list.cc
index 4574e340..13346d0b 100644
--- a/src/core/download_list.cc
+++ b/src/core/download_list.cc
@@ -315,7 +315,8 @@ DownloadList::resume(Download* download) {
return;
}
- open_throw(download);
+ // This will never actually do anything due to the above hash check.
+ // open_throw(download);
download->variable()->set("state_changed", cachedTime.seconds());
diff --git a/src/core/manager.cc b/src/core/manager.cc
index c08e9ffe..2d7d81e0 100644
--- a/src/core/manager.cc
+++ b/src/core/manager.cc
@@ -491,65 +491,58 @@ Manager::receive_hashing_changed() {
// Try quick hashing all those with hashing == initial, set them to
// something else when failed.
- for (View::iterator itr = m_hashingView->begin_visible(), last = m_hashingView->end_visible(); itr != last; ++itr)
- try {
-
- if ((*itr)->is_hash_checking()) {
- foundHashing = true;
- continue;
- }
-
- if ((*itr)->is_hash_checked())
- throw torrent::internal_error("core::Manager::receive_hashing_changed() hash already checked or checking.");
+ for (View::iterator itr = m_hashingView->begin_visible(), last = m_hashingView->end_visible(); itr != last; ++itr) {
+ if ((*itr)->is_hash_checked())
+ throw torrent::internal_error("core::Manager::receive_hashing_changed() hash already checked or checking.");
- if ((*itr)->is_hash_failed() ||
- (*itr)->variable()->get_value("hashing") != Download::variable_hashing_initial ||
- (*itr)->download()->chunks_hashed() != 0)
- continue;
+ if ((*itr)->is_hash_checking()) {
+ foundHashing = true;
+ continue;
+ }
+ if ((*itr)->is_hash_failed())
+ continue;
+
+ bool tryQuick =
+ (*itr)->variable()->get_value("hashing") == Download::variable_hashing_initial &&
+ (*itr)->download()->file_list()->bitfield()->empty();
+
+ if (!tryQuick && foundHashing)
+ continue;
+
+ try {
m_downloadList->open_throw(*itr);
- torrent::resume_load_progress(*(*itr)->download(), (*itr)->download()->bencode()->get_key("libtorrent_resume"));
- if ((*itr)->download()->hash_check(true)) {
- // Set this to exit the function so that the delayed hash done
- // signal gets triggered before we try any real hashing.
- foundHashing = true;
+ // Since the bitfield is allocated on loading of resume load or
+ // hash start, and unallocated on close, we know that if it it
+ // not empty then we have loaded any existing resume data.
+ if ((*itr)->download()->file_list()->bitfield()->empty())
+ torrent::resume_load_progress(*(*itr)->download(), (*itr)->download()->bencode()->get_key("libtorrent_resume"));
+
+ // Need to clean up the below.
+ if (tryQuick) {
+ if (!(*itr)->download()->hash_check(true))
+ // Temporary hack.
+ (*itr)->download()->hash_stop();
+
+ // Make sure we don't repeat the quick hashing.
+ (*itr)->variable()->set_value("hashing", Download::variable_hashing_rehash);
} else {
- // Temporary hack.
- (*itr)->download()->hash_stop();
+ (*itr)->download()->hash_check(false);
}
- (*itr)->variable()->set_value("hashing", Download::variable_hashing_rehash);
-
} catch (torrent::local_error& e) {
- (*itr)->set_hash_failed(true);
- push_log(e.what());
- }
-
- if (foundHashing)
- return;
-
- for (View::iterator itr = m_hashingView->begin_visible(), last = m_hashingView->end_visible(); itr != last; ++itr)
- try {
-
- if ((*itr)->is_hash_checked() || (*itr)->is_hash_checking())
- throw torrent::internal_error("core::Manager::receive_hashing_changed() hash already checked or checking.");
-
- if ((*itr)->is_hash_failed())
- continue;
-
- m_downloadList->open_throw(*itr);
- torrent::resume_load_progress(*(*itr)->download(), (*itr)->download()->bencode()->get_key("libtorrent_resume"));
-
- (*itr)->download()->hash_check(false);
-
- return;
-
- } catch (torrent::local_error& e) {
- (*itr)->set_hash_failed(true);
- push_log(e.what());
+ if (tryQuick) {
+ // Make sure we don't repeat the quick hashing.
+ (*itr)->variable()->set_value("hashing", Download::variable_hashing_rehash);
+
+ } else {
+ (*itr)->set_hash_failed(true);
+ push_log(e.what());
+ }
}
+ }
}
}
diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc
index ac4ca897..5cd1c0b1 100644
--- a/src/display/window_file_list.cc
+++ b/src/display/window_file_list.cc
@@ -36,23 +36,24 @@
#include "config.h"
-#include
-#include
#include
#include
#include
#include
#include "core/download.h"
+#include "ui/element_file_list.h"
#include "window_file_list.h"
namespace display {
-WindowFileList::WindowFileList(core::Download* d, iterator* selected) :
+// Don't really like the direction of the element dependency, but
+// don't really feel like making a seperate class for containing the
+// necessary information.
+WindowFileList::WindowFileList(const ui::ElementFileList* element) :
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
- m_download(d),
- m_selected(selected) {
+ m_element(element) {
}
/*
@@ -77,17 +78,50 @@ WindowFileList::redraw() {
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(10)).round_seconds());
m_canvas->erase();
- torrent::FileList* fl = m_download->download()->file_list();
+ torrent::FileList* fl = m_element->download()->download()->file_list();
if (fl->size_files() == 0 || m_canvas->height() < 2)
return;
- unsigned int pos = 0;
- iterator itr = rak::advance_bidirectional(iterator(fl->begin()), *m_selected, iterator(fl->end()), m_canvas->height() - 1).first;
+ iterator entries[m_canvas->height() - 1];
+ unsigned int last = 0;
+
+ for (iterator itr = m_element->selected(); last != m_canvas->height() - 1; ) {
+ if (m_element->is_collapsed())
+ itr.forward_current_depth();
+ else
+ ++itr;
+
+ entries[last++] = itr;
+
+ if (itr == iterator(fl->end()))
+ break;
+ }
+
+ unsigned int first = m_canvas->height() - 1;
+
+ for (iterator itr = m_element->selected(); first >= last || first > (m_canvas->height() - 1) / 2; ) {
+ entries[--first] = itr;
+
+ if (itr == iterator(fl->begin()))
+ break;
+
+ if (m_element->is_collapsed())
+ itr.backward_current_depth();
+ else
+ --itr;
+ }
+
+ unsigned int pos = 0;
m_canvas->print(0, pos++, "Cmp Pri Size Filename");
- while (pos != m_canvas->height() && itr != iterator(fl->end())) {
+ while (pos != m_canvas->height()) {
+ iterator itr = entries[first];
+
+ if (itr == iterator(fl->end()))
+ break;
+
if (itr.is_empty()) {
m_canvas->print(16, pos, "EMPTY");
@@ -136,11 +170,11 @@ WindowFileList::redraw() {
m_canvas->print(0, pos, "BORK BORK");
}
- if (itr == *m_selected)
+ if (itr == m_element->selected())
m_canvas->set_attr(0, pos, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0));
- ++itr;
- ++pos;
+ pos++;
+ first = (first + 1) % (m_canvas->height() - 1);
}
}
diff --git a/src/display/window_file_list.h b/src/display/window_file_list.h
index ab11c371..8f4c4f08 100644
--- a/src/display/window_file_list.h
+++ b/src/display/window_file_list.h
@@ -37,34 +37,33 @@
#ifndef RTORRENT_DISPLAY_FILE_LIST_H
#define RTORRENT_DISPLAY_FILE_LIST_H
-#include
-
#include "window.h"
+namespace ui {
+ class ElementFileList;
+}
+
namespace torrent {
class File;
class FileListIterator;
-}
-
-namespace core {
- class Download;
+ class file_list_collapsed_iterator;
}
namespace display {
class WindowFileList : public Window {
public:
- typedef torrent::FileListIterator iterator;
+ typedef torrent::FileListIterator iterator;
+ typedef torrent::file_list_collapsed_iterator collapsed_iterator;
- WindowFileList(core::Download* d, iterator* selected);
+ WindowFileList(const ui::ElementFileList* element);
virtual void redraw();
private:
int done_percentage(torrent::File* e);
- core::Download* m_download;
- iterator* m_selected;
+ const ui::ElementFileList* m_element;
};
}
diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc
index 0e8cfc23..9ce88be7 100644
--- a/src/ui/element_file_list.cc
+++ b/src/ui/element_file_list.cc
@@ -62,13 +62,15 @@ ElementFileList::ElementFileList(core::Download* d) :
m_window(NULL),
m_elementInfo(NULL),
- m_selected(iterator(d->download()->file_list()->begin())) {
+ m_selected(iterator(d->download()->file_list()->begin())),
+ m_collapsed(false) {
m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = sigc::mem_fun(&m_slotExit, &slot_type::operator());
- m_bindings[KEY_RIGHT] = m_bindings['F' - '@'] = sigc::bind(sigc::mem_fun(this, &ElementFileList::activate_display), DISPLAY_INFO);
+ m_bindings[KEY_RIGHT] = m_bindings['F' - '@'] = sigc::mem_fun(*this, &ElementFileList::receive_select);
m_bindings[' '] = sigc::mem_fun(*this, &ElementFileList::receive_priority);
m_bindings['*'] = sigc::mem_fun(*this, &ElementFileList::receive_change_all);
+ m_bindings['/'] = sigc::mem_fun(*this, &ElementFileList::receive_collapse);
m_bindings[KEY_NPAGE] = sigc::mem_fun(*this, &ElementFileList::receive_pagenext);
m_bindings[KEY_PPAGE] = sigc::mem_fun(*this, &ElementFileList::receive_pageprev);
@@ -119,7 +121,7 @@ ElementFileList::activate(display::Frame* frame, bool focus) {
if (focus)
control->input()->push_back(&m_bindings);
- m_window = new WFileList(m_download, &m_selected);
+ m_window = new WFileList(this);
m_window->set_active(true);
m_window->set_focused(focus);
@@ -193,7 +195,12 @@ void
ElementFileList::receive_next() {
torrent::FileList* fl = m_download->download()->file_list();
- if (m_selected == iterator(fl->end()) || ++m_selected == iterator(fl->end()))
+ if (is_collapsed())
+ m_selected.forward_current_depth();
+ else
+ m_selected++;
+
+ if (m_selected == iterator(fl->end()))
m_selected = iterator(fl->begin());
update_itr();
@@ -206,7 +213,11 @@ ElementFileList::receive_prev() {
if (m_selected == iterator(fl->begin()))
m_selected = iterator(fl->end());
- m_selected--;
+ if (is_collapsed())
+ m_selected.backward_current_depth();
+ else
+ m_selected--;
+
update_itr();
}
@@ -230,7 +241,7 @@ ElementFileList::receive_pagenext() {
void
ElementFileList::receive_pageprev() {
if (m_window == NULL)
- throw torrent::internal_error("ui::ElementFileList::receive_pageprev(...) called on a disabled object");
+ return;
torrent::FileList* fl = m_download->download()->file_list();
@@ -242,33 +253,29 @@ ElementFileList::receive_pageprev() {
update_itr();
}
-// Take a range as input and return the next entry at the same
-// directory depth as first. If the returned iterator equals 'last' or
-// is_leaving() == true then the search failed. UHM... wrong...
+void
+ElementFileList::receive_select() {
+ if (m_window == NULL || m_state != DISPLAY_LIST)
+ return;
-torrent::FileListIterator
-next_current_depth(torrent::FileListIterator first, torrent::FileListIterator last) {
- if (first == last)
- return first;
-
- uint32_t depth = (first++).depth();
-
- while (first != last && (first.depth() > depth || first.is_leaving()))
- ++first;
-
- return first;
+ if (is_collapsed() && !m_selected.is_file()) {
+ m_selected++;
+ m_window->mark_dirty();
+ } else {
+ activate_display(DISPLAY_INFO);
+ }
}
void
ElementFileList::receive_priority() {
if (m_window == NULL)
- throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object");
+ return;
- torrent::FileList* fl = m_download->download()->file_list();
torrent::priority_t priority = torrent::priority_t((m_selected.file()->priority() + 2) % 3);
iterator first = m_selected;
- iterator last = next_current_depth(m_selected, iterator(fl->end()));
+ iterator last = m_selected;
+ last.forward_current_depth();
while (first != last) {
if (first.is_file())
@@ -284,7 +291,7 @@ ElementFileList::receive_priority() {
void
ElementFileList::receive_change_all() {
if (m_window == NULL)
- throw torrent::internal_error("ui::ElementFileList::receive_prev(...) called on a disabled object");
+ return;
torrent::FileList* fl = m_download->download()->file_list();
torrent::priority_t priority = torrent::priority_t((m_selected.file()->priority() + 2) % 3);
@@ -296,6 +303,15 @@ ElementFileList::receive_change_all() {
update_itr();
}
+void
+ElementFileList::receive_collapse() {
+ if (m_window == NULL)
+ return;
+
+ set_collapsed(!is_collapsed());
+ m_window->mark_dirty();
+}
+
void
ElementFileList::update_itr() {
m_window->mark_dirty();
diff --git a/src/ui/element_file_list.h b/src/ui/element_file_list.h
index cae5c1b7..e71cb14d 100644
--- a/src/ui/element_file_list.h
+++ b/src/ui/element_file_list.h
@@ -44,8 +44,6 @@
#include "element_base.h"
-class Control;
-
namespace display {
class WindowFileList;
}
@@ -72,14 +70,23 @@ public:
void activate_display(Display display);
+ bool is_collapsed() const { return m_collapsed; }
+ void set_collapsed(bool s) { m_collapsed = s; }
+
+ iterator selected() const { return m_selected; }
+ core::Download* download() const { return m_download; }
+
private:
void receive_next();
void receive_prev();
void receive_pagenext();
void receive_pageprev();
+ void receive_select();
+
void receive_priority();
void receive_change_all();
+ void receive_collapse();
void update_itr();
@@ -91,6 +98,7 @@ private:
// Change to unsigned, please.
iterator m_selected;
+ bool m_collapsed;
};
}