mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-15 05:36:17 +00:00
* 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:
+13
-11
@@ -808,21 +808,23 @@ number of criteria, including zero, from the following:
|
|||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<!-- <varlistentry> -->
|
||||||
<term>view_filter = <replaceable>name</replaceable>,<replaceable>...</replaceable></term>
|
<!-- <term>view_filter = <replaceable>command</replaceable></term> -->
|
||||||
<listitem><para>
|
<!-- <listitem><para> -->
|
||||||
|
|
||||||
Set a list of filter to apply when new new downloads are added and
|
<!-- Set a list of filter to apply when new new downloads are added and -->
|
||||||
when <emphasis>view_sort</emphasis> is called. All filters must
|
<!-- when <emphasis>view_sort</emphasis> is called. All filters must -->
|
||||||
match for the download to be included.
|
<!-- match for the download to be included. -->
|
||||||
|
|
||||||
</para><para>
|
|
||||||
|
|
||||||
<emphasis>stopped</emphasis>, <emphasis>started</emphasis>,
|
|
||||||
<emphasis>complete</emphasis>, <emphasis>incomplete</emphasis>,
|
|
||||||
|
|
||||||
</para></listitem>
|
<!-- </para><para> -->
|
||||||
</varlistentry>
|
|
||||||
|
<!-- <emphasis>stopped</emphasis>, <emphasis>started</emphasis>, -->
|
||||||
|
<!-- <emphasis>complete</emphasis>, <emphasis>incomplete</emphasis>, -->
|
||||||
|
|
||||||
|
<!-- </para></listitem> -->
|
||||||
|
<!-- </varlistentry> -->
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>key_layout = <replaceable>qwerty|azerty|qwertz|dvorak</replaceable></term>
|
<term>key_layout = <replaceable>qwerty|azerty|qwertz|dvorak</replaceable></term>
|
||||||
|
|||||||
@@ -393,6 +393,9 @@ initialize_command_ui() {
|
|||||||
ADD_COMMAND_LIST("view_sort_new", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_sort_new));
|
ADD_COMMAND_LIST("view_sort_new", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_sort_new));
|
||||||
ADD_COMMAND_LIST("view_sort_current", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_sort_current));
|
ADD_COMMAND_LIST("view_sort_current", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_sort_current));
|
||||||
|
|
||||||
|
ADD_COMMAND_LIST("view_event_added", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_event_added));
|
||||||
|
ADD_COMMAND_LIST("view_event_removed", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_event_removed));
|
||||||
|
|
||||||
// Move.
|
// Move.
|
||||||
|
|
||||||
ADD_ANY_NONE("print", rak::ptr_fn(&apply_print));
|
ADD_ANY_NONE("print", rak::ptr_fn(&apply_print));
|
||||||
|
|||||||
+50
-13
@@ -171,12 +171,34 @@ View::sort() {
|
|||||||
|
|
||||||
void
|
void
|
||||||
View::filter() {
|
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);
|
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
|
void
|
||||||
@@ -225,10 +247,13 @@ View::received(core::Download* download, int event) {
|
|||||||
if (itr != base_type::end())
|
if (itr != base_type::end())
|
||||||
throw torrent::internal_error("View::received(..., SLOTS_INSERT) already inserted.");
|
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);
|
insert_visible(download);
|
||||||
else
|
rpc::parse_command_multiple_d_nothrow(download, m_eventAdded);
|
||||||
|
|
||||||
|
} else {
|
||||||
base_type::insert(end_filtered(), download);
|
base_type::insert(end_filtered(), download);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_focus > m_size)
|
if (m_focus > m_size)
|
||||||
throw torrent::internal_error("View::received(...) 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:
|
case DownloadList::SLOTS_ERASE:
|
||||||
erase(itr);
|
erase(itr);
|
||||||
|
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -245,20 +272,30 @@ View::received(core::Download* download, int event) {
|
|||||||
|
|
||||||
if (view_downloads_filter(m_filter)(download)) {
|
if (view_downloads_filter(m_filter)(download)) {
|
||||||
|
|
||||||
// Erase even if it is in visible so that the download is
|
if (itr >= end_visible()) {
|
||||||
// re-sorted.
|
// Erase even if it is in visible so that the download is
|
||||||
//
|
// re-sorted.
|
||||||
// Do we really want to do this?
|
//
|
||||||
erase(itr);
|
// This isn't the best solution...
|
||||||
insert_visible(download);
|
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 {
|
} else {
|
||||||
|
if (itr >= end_visible())
|
||||||
if (itr >= begin_filtered())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
erase(itr);
|
erase(itr);
|
||||||
base_type::push_back(download);
|
base_type::push_back(download);
|
||||||
|
|
||||||
|
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ public:
|
|||||||
|
|
||||||
void clear_filter_on();
|
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
|
// 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
|
// user-dependent. Used by f.ex. ViewManager to decide if it should
|
||||||
// sort and/or filter a view.
|
// sort and/or filter a view.
|
||||||
@@ -159,6 +162,9 @@ private:
|
|||||||
|
|
||||||
std::string m_filter;
|
std::string m_filter;
|
||||||
|
|
||||||
|
std::string m_eventAdded;
|
||||||
|
std::string m_eventRemoved;
|
||||||
|
|
||||||
rak::timer m_lastChanged;
|
rak::timer m_lastChanged;
|
||||||
signal_type m_signalChanged;
|
signal_type m_signalChanged;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -104,20 +104,6 @@ ViewManager::sort(const std::string& name, uint32_t timeout) {
|
|||||||
(*viewItr)->sort();
|
(*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
|
void
|
||||||
ViewManager::set_filter(const std::string& name, const std::string& cmd) {
|
ViewManager::set_filter(const std::string& name, const std::string& cmd) {
|
||||||
iterator viewItr = find_throw(name);
|
iterator viewItr = find_throw(name);
|
||||||
|
|||||||
@@ -87,12 +87,16 @@ public:
|
|||||||
// Find a better name for 'timeout'.
|
// Find a better name for 'timeout'.
|
||||||
void sort(const std::string& name, uint32_t timeout = 0);
|
void sort(const std::string& name, uint32_t timeout = 0);
|
||||||
|
|
||||||
void set_sort_new(const std::string& name, const std::string& cmd);
|
// These could be moved to where the command is implemented.
|
||||||
void set_sort_current(const std::string& name, const std::string& cmd);
|
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(const std::string& name, const std::string& cmd);
|
||||||
void set_filter_on(const std::string& name, const filter_args& args);
|
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:
|
private:
|
||||||
DownloadList* m_list;
|
DownloadList* m_list;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ parse_command_single_std(const std::string& cmd) {
|
|||||||
parse_command(make_target(), cmd.c_str(), cmd.c_str() + cmd.size());
|
parse_command(make_target(), cmd.c_str(), cmd.c_str() + cmd.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
parse_command_multiple_d_nothrow(core::Download* download, const std::string& cmd) {
|
||||||
|
try {
|
||||||
|
parse_command_multiple(make_target(download), cmd.c_str(), cmd.c_str() + cmd.size());
|
||||||
|
} catch (torrent::input_error& e) {
|
||||||
|
// Log?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
parse_command_d_single_std(core::Download* download, const std::string& cmd) {
|
parse_command_d_single_std(core::Download* download, const std::string& cmd) {
|
||||||
parse_command(make_target(download), cmd.c_str(), cmd.c_str() + cmd.size());
|
parse_command(make_target(download), cmd.c_str(), cmd.c_str() + cmd.size());
|
||||||
|
|||||||
+3
-1
@@ -137,6 +137,7 @@ xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
|
|
||||||
switch (xmlrpc_value_type(value)) {
|
switch (xmlrpc_value_type(value)) {
|
||||||
case XMLRPC_TYPE_STRING:
|
case XMLRPC_TYPE_STRING:
|
||||||
|
{
|
||||||
const char* str;
|
const char* str;
|
||||||
xmlrpc_read_string(env, value, &str);
|
xmlrpc_read_string(env, value, &str);
|
||||||
|
|
||||||
@@ -209,6 +210,7 @@ xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index.");
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index.");
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return rpc::make_target();
|
return rpc::make_target();
|
||||||
@@ -537,7 +539,7 @@ void XmlRpc::set_dialect(__UNUSED int dialect) {}
|
|||||||
bool XmlRpc::process(__UNUSED const char* inBuffer, __UNUSED uint32_t length, __UNUSED slot_write slotWrite) { return false; }
|
bool XmlRpc::process(__UNUSED const char* inBuffer, __UNUSED uint32_t length, __UNUSED slot_write slotWrite) { return false; }
|
||||||
|
|
||||||
int64_t XmlRpc::size_limit() { return 0; }
|
int64_t XmlRpc::size_limit() { return 0; }
|
||||||
void XmlRpc::set_size_limit(int64_t size) {}
|
void XmlRpc::set_size_limit(uint64_t size) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user