* Added view_event_{added,removed} commands that sets a command to be

triggered when a download is added/removed from the specified view.

* Minor compiler errors fixed.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1045 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2008-03-20 11:50:57 +00:00
parent 7062935724
commit 199bd1985c
8 changed files with 90 additions and 41 deletions
+50 -13
View File
@@ -171,12 +171,34 @@ View::sort() {
void
View::filter() {
iterator split = std::stable_partition(base_type::begin(), base_type::end(), view_downloads_filter(m_filter));
// Parition the list in two steps so we know which elements changed.
iterator splitVisible = std::stable_partition(begin_visible(), end_visible(), view_downloads_filter(m_filter));
iterator splitFiltered = std::stable_partition(begin_filtered(), end_filtered(), view_downloads_filter(m_filter));
m_size = position(split);
base_type changed(splitVisible, splitFiltered);
iterator splitChanged = changed.begin() + std::distance(splitVisible, end_visible());
m_size = std::distance(begin(), std::copy(splitChanged, changed.end(), splitVisible));
std::copy(changed.begin(), splitChanged, begin_filtered());
// Fix focus
// Fix this...
m_focus = std::min(m_focus, m_size);
// The commands are allowed to remove itself from or change View
// sorting since the commands are being called on the 'changed'
// vector. But this will cause undefined behavior if elements are
// removed.
//
// Consider if View should lock itself (and throw) if erase events
// are triggered on a Download in the 'changed' list. This can be
// done by using a base_type* member variable, and making sure we
// set the elements to NULL as we trigger commands on them. Or
// perhaps always clear them, thus not throwing anything.
if (!m_eventRemoved.empty())
std::for_each(changed.begin(), splitChanged, rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventRemoved));
if (!m_eventAdded.empty())
std::for_each(splitChanged, changed.end(), rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventAdded));
}
void
@@ -225,10 +247,13 @@ View::received(core::Download* download, int event) {
if (itr != base_type::end())
throw torrent::internal_error("View::received(..., SLOTS_INSERT) already inserted.");
if (view_downloads_filter(m_filter)(download))
if (view_downloads_filter(m_filter)(download)) {
insert_visible(download);
else
rpc::parse_command_multiple_d_nothrow(download, m_eventAdded);
} else {
base_type::insert(end_filtered(), download);
}
if (m_focus > m_size)
throw torrent::internal_error("View::received(...) m_focus > m_size.");
@@ -237,6 +262,8 @@ View::received(core::Download* download, int event) {
case DownloadList::SLOTS_ERASE:
erase(itr);
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
break;
default:
@@ -245,20 +272,30 @@ View::received(core::Download* download, int event) {
if (view_downloads_filter(m_filter)(download)) {
// Erase even if it is in visible so that the download is
// re-sorted.
//
// Do we really want to do this?
erase(itr);
insert_visible(download);
if (itr >= end_visible()) {
// Erase even if it is in visible so that the download is
// re-sorted.
//
// This isn't the best solution...
erase(itr);
insert_visible(download);
rpc::parse_command_multiple_d_nothrow(download, m_eventAdded);
} else {
// Should we really sort it here, or just return?
erase(itr);
insert_visible(download);
}
} else {
if (itr >= begin_filtered())
if (itr >= end_visible())
return;
erase(itr);
base_type::push_back(download);
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
}
break;
+6
View File
@@ -118,6 +118,9 @@ public:
void clear_filter_on();
void set_event_added(const std::string& cmd) { m_eventAdded = cmd; }
void set_event_removed(const std::string& cmd) { m_eventRemoved = cmd; }
// The time of the last change to the view, semantics of this is
// user-dependent. Used by f.ex. ViewManager to decide if it should
// sort and/or filter a view.
@@ -159,6 +162,9 @@ private:
std::string m_filter;
std::string m_eventAdded;
std::string m_eventRemoved;
rak::timer m_lastChanged;
signal_type m_signalChanged;
};
-14
View File
@@ -104,20 +104,6 @@ ViewManager::sort(const std::string& name, uint32_t timeout) {
(*viewItr)->sort();
}
void
ViewManager::set_sort_new(const std::string& name, const std::string& cmd) {
iterator viewItr = find_throw(name);
(*viewItr)->set_sort_new(cmd);
}
void
ViewManager::set_sort_current(const std::string& name, const std::string& cmd) {
iterator viewItr = find_throw(name);
(*viewItr)->set_sort_current(cmd);
}
void
ViewManager::set_filter(const std::string& name, const std::string& cmd) {
iterator viewItr = find_throw(name);
+6 -2
View File
@@ -87,12 +87,16 @@ public:
// Find a better name for 'timeout'.
void sort(const std::string& name, uint32_t timeout = 0);
void set_sort_new(const std::string& name, const std::string& cmd);
void set_sort_current(const std::string& name, const std::string& cmd);
// These could be moved to where the command is implemented.
void set_sort_new(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_sort_new(cmd); }
void set_sort_current(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_sort_current(cmd); }
void set_filter(const std::string& name, const std::string& cmd);
void set_filter_on(const std::string& name, const filter_args& args);
void set_event_added(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_added(cmd); }
void set_event_removed(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_removed(cmd); }
private:
DownloadList* m_list;
};