mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-11 12:42:31 +00:00
* Changed view_filter to use boolean commands instead of custom
functors. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1042 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
+62
-1
@@ -53,6 +53,7 @@
|
||||
#include "command_helpers.h"
|
||||
|
||||
typedef void (core::ViewManager::*view_filter_slot)(const std::string&, const core::ViewManager::sort_args&);
|
||||
typedef void (core::ViewManager::*view_cfilter_slot)(const std::string&, const std::string&);
|
||||
|
||||
torrent::Object
|
||||
apply_view_filter(view_filter_slot viewFilterSlot, const torrent::Object& rawArgs) {
|
||||
@@ -76,6 +77,23 @@ apply_view_filter(view_filter_slot viewFilterSlot, const torrent::Object& rawArg
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_view_cfilter(view_cfilter_slot viewFilterSlot, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.size() != 2)
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
const std::string& name = args.front().as_string();
|
||||
|
||||
if (name.empty())
|
||||
throw torrent::input_error("First argument must be a string.");
|
||||
|
||||
(control->view_manager()->*viewFilterSlot)(name, args.back().as_string());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_view_sort(const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
@@ -144,6 +162,46 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
as_boolean(const torrent::Object& rawArgs) {
|
||||
switch (rawArgs.type()) {
|
||||
case torrent::Object::TYPE_VALUE: return rawArgs.as_value();
|
||||
case torrent::Object::TYPE_STRING: return !rawArgs.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST: return !rawArgs.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP: return !rawArgs.as_map().empty();
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_not(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
return (int64_t)as_boolean(rawArgs);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_and(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
if (rawArgs.type() != torrent::Object::TYPE_LIST)
|
||||
return as_boolean(rawArgs);
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
|
||||
if (!as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
return (int64_t)false;
|
||||
|
||||
return (int64_t)true;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_or(rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
if (rawArgs.type() != torrent::Object::TYPE_LIST)
|
||||
return as_boolean(rawArgs);
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(), last = rawArgs.as_list().end(); itr != last; itr++)
|
||||
if (as_boolean(rpc::parse_command_single(target, itr->as_string())))
|
||||
return (int64_t)true;
|
||||
|
||||
return (int64_t)false;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_to_time(int flags, const torrent::Object& rawArgs) {
|
||||
std::tm *u;
|
||||
@@ -287,7 +345,7 @@ initialize_command_ui() {
|
||||
ADD_COMMAND_NONE_L("view_list", rak::ptr_fn(&apply_view_list));
|
||||
ADD_COMMAND_NONE_L("view_set", rak::ptr_fn(&apply_view_set));
|
||||
|
||||
ADD_COMMAND_LIST("view_filter", rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_filter));
|
||||
ADD_COMMAND_LIST("view_filter", rak::bind_ptr_fn(&apply_view_cfilter, &core::ViewManager::set_filter));
|
||||
ADD_COMMAND_LIST("view_filter_on", rak::bind_ptr_fn(&apply_view_filter, &core::ViewManager::set_filter_on));
|
||||
|
||||
ADD_COMMAND_LIST("view_sort", rak::ptr_fn(&apply_view_sort));
|
||||
@@ -301,6 +359,9 @@ initialize_command_ui() {
|
||||
ADD_ANY_NONE("print", rak::ptr_fn(&apply_print));
|
||||
ADD_ANY_NONE("cat", rak::ptr_fn(&apply_cat));
|
||||
ADD_ANY_NONE("if", rak::bind_ptr_fn(&apply_if, 0));
|
||||
ADD_ANY_NONE("not", rak::ptr_fn(&apply_not));
|
||||
ADD_ANY_NONE("and", rak::ptr_fn(&apply_and));
|
||||
ADD_ANY_NONE("or", rak::ptr_fn(&apply_or));
|
||||
|
||||
// A temporary command for handling stuff until we get proper
|
||||
// support for seperation of commands and literals.
|
||||
|
||||
+22
-8
@@ -39,6 +39,7 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <rak/functional.h>
|
||||
#include <rpc/parse_commands.h>
|
||||
#include <sigc++/adaptors/bind.h>
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/exceptions.h>
|
||||
@@ -128,19 +129,30 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
|
||||
};
|
||||
|
||||
struct view_downloads_filter : std::unary_function<Download*, bool> {
|
||||
view_downloads_filter(const View::filter_list& s) : m_filter(s) {}
|
||||
view_downloads_filter(const std::string& cmd) : m_command(cmd) {}
|
||||
|
||||
bool operator () (Download* d1) const {
|
||||
for (View::filter_list::const_iterator itr = m_filter.begin(), last = m_filter.end(); itr != last; ++itr)
|
||||
if (!(**itr)(d1))
|
||||
return false;
|
||||
try {
|
||||
torrent::Object result = rpc::parse_command_single(rpc::make_target(d1), m_command);
|
||||
|
||||
// The default filter action is to return true, to not filter the
|
||||
// download out.
|
||||
return true;
|
||||
switch (result.type()) {
|
||||
case torrent::Object::TYPE_NONE: return false;
|
||||
case torrent::Object::TYPE_VALUE: return result.as_value();
|
||||
case torrent::Object::TYPE_STRING: return !result.as_string().empty();
|
||||
case torrent::Object::TYPE_LIST: return !result.as_list().empty();
|
||||
case torrent::Object::TYPE_MAP: return !result.as_map().empty();
|
||||
}
|
||||
|
||||
// The default filter action is to return true, to not filter
|
||||
// the download out.
|
||||
return true;
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const View::filter_list& m_filter;
|
||||
const std::string& m_command;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -232,6 +244,8 @@ View::received(core::Download* download, int event) {
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
+3
-14
@@ -62,14 +62,12 @@ namespace core {
|
||||
class Download;
|
||||
class DownloadList;
|
||||
class ViewSort;
|
||||
class ViewFilter;
|
||||
|
||||
class View : private std::vector<Download*> {
|
||||
public:
|
||||
typedef std::vector<Download*> base_type;
|
||||
typedef sigc::signal0<void> signal_type;
|
||||
typedef std::vector<const ViewSort*> sort_list;
|
||||
typedef std::vector<const ViewFilter*> filter_list;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
@@ -117,10 +115,9 @@ public:
|
||||
// Need to explicity trigger filtering.
|
||||
void filter();
|
||||
|
||||
void set_filter(const filter_list& s) { m_filter = s; }
|
||||
void set_filter(const std::string& s) { m_filter = s; }
|
||||
void set_filter_on(int event);
|
||||
|
||||
void set_cfilter(const std::string& s) { m_cfilter = s; }
|
||||
|
||||
void clear_filter_on();
|
||||
|
||||
@@ -162,9 +159,8 @@ private:
|
||||
sort_list m_sortNew;
|
||||
sort_list m_sortCurrent;
|
||||
|
||||
filter_list m_filter;
|
||||
|
||||
std::string m_cfilter;
|
||||
// This should be replaced by a faster non-string command type.
|
||||
std::string m_filter;
|
||||
|
||||
rak::timer m_lastChanged;
|
||||
signal_type m_signalChanged;
|
||||
@@ -177,13 +173,6 @@ public:
|
||||
virtual bool operator () (Download* d1, Download* d2) const = 0;
|
||||
};
|
||||
|
||||
class ViewFilter {
|
||||
public:
|
||||
virtual ~ViewFilter() {}
|
||||
|
||||
virtual bool operator () (Download* d1) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -111,21 +111,6 @@ private:
|
||||
ViewSort* m_sort;
|
||||
};
|
||||
|
||||
class ViewFilterVariableValue : public ViewFilter {
|
||||
public:
|
||||
ViewFilterVariableValue(const char* name, torrent::Object::value_type v, bool inverse = false) :
|
||||
m_name(name), m_value(v), m_inverse(inverse) {}
|
||||
|
||||
virtual bool operator () (Download* d1) const {
|
||||
return (rpc::call_command_value(m_name, rpc::make_target(d1)) == m_value) != m_inverse;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* m_name;
|
||||
torrent::Object::value_type m_value;
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
// Really need to implement a factory and allow options in the sort
|
||||
// statements.
|
||||
ViewManager::ViewManager(DownloadList* dl) :
|
||||
@@ -143,19 +128,12 @@ ViewManager::ViewManager(DownloadList* dl) :
|
||||
|
||||
m_sort["state_changed"] = new ViewSortVariableValue("d.get_state_changed");
|
||||
m_sort["state_changed_reverse"] = new ViewSortVariableValue("d.get_state_changed", true);
|
||||
|
||||
m_filter["started"] = new ViewFilterVariableValue("d.get_state", 1);
|
||||
m_filter["stopped"] = new ViewFilterVariableValue("d.get_state", 0);
|
||||
m_filter["complete"] = new ViewFilterVariableValue("d.get_complete", 0, true);
|
||||
m_filter["incomplete"] = new ViewFilterVariableValue("d.get_complete", 0);
|
||||
m_filter["hashing"] = new ViewFilterVariableValue("d.get_hashing", 0, true);
|
||||
}
|
||||
|
||||
void
|
||||
ViewManager::clear() {
|
||||
std::for_each(begin(), end(), rak::call_delete<View>());
|
||||
std::for_each(m_sort.begin(), m_sort.end(), rak::on(rak::mem_ref(&sort_map::value_type::second), rak::call_delete<ViewSort>()));
|
||||
std::for_each(m_filter.begin(), m_filter.end(), rak::on(rak::mem_ref(&filter_map::value_type::second), rak::call_delete<ViewFilter>()));
|
||||
|
||||
base_type::clear();
|
||||
}
|
||||
@@ -230,28 +208,11 @@ ViewManager::set_sort_current(const std::string& name, const sort_args& sort) {
|
||||
(*viewItr)->set_sort_current(build_sort_list(sort));
|
||||
}
|
||||
|
||||
inline ViewManager::filter_list
|
||||
ViewManager::build_filter_list(const filter_args& args) {
|
||||
View::filter_list filterList;
|
||||
filterList.reserve(args.size());
|
||||
|
||||
for (filter_args::const_iterator itr = args.begin(), last = args.end(); itr != last; ++itr) {
|
||||
filter_map::const_iterator filterItr = m_filter.find(itr->c_str());
|
||||
|
||||
if (filterItr == m_filter.end())
|
||||
throw torrent::input_error("Invalid filtering identifier.");
|
||||
|
||||
filterList.push_back(filterItr->second);
|
||||
}
|
||||
|
||||
return filterList;
|
||||
}
|
||||
|
||||
void
|
||||
ViewManager::set_filter(const std::string& name, const filter_args& args) {
|
||||
ViewManager::set_filter(const std::string& name, const std::string& cmd) {
|
||||
iterator viewItr = find_throw(name);
|
||||
|
||||
(*viewItr)->set_filter(build_filter_list(args));
|
||||
(*viewItr)->set_filter(cmd);
|
||||
(*viewItr)->filter();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
typedef View::sort_list sort_list;
|
||||
typedef std::list<std::string> sort_args;
|
||||
|
||||
typedef std::map<const char*, ViewFilter*, view_manager_comp> filter_map;
|
||||
typedef View::filter_list filter_list;
|
||||
typedef std::list<std::string> filter_args;
|
||||
|
||||
using base_type::iterator;
|
||||
@@ -105,17 +103,15 @@ public:
|
||||
void set_sort_new(const std::string& name, const sort_args& sort);
|
||||
void set_sort_current(const std::string& name, const sort_args& sort);
|
||||
|
||||
void set_filter(const std::string& name, const filter_args& args);
|
||||
void set_filter(const std::string& name, const std::string& cmd);
|
||||
void set_filter_on(const std::string& name, const filter_args& args);
|
||||
|
||||
private:
|
||||
inline sort_list build_sort_list(const sort_args& args);
|
||||
inline filter_list build_filter_list(const sort_args& args);
|
||||
|
||||
DownloadList* m_list;
|
||||
|
||||
sort_map m_sort;
|
||||
filter_map m_filter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -184,38 +184,38 @@ main(int argc, char** argv) {
|
||||
"view_sort_current = name,name\n"
|
||||
|
||||
"view_add = started\n"
|
||||
"view_filter = started,started\n"
|
||||
"view_filter = started,d.get_state=\n"
|
||||
"view_filter_on = started,start,stop\n"
|
||||
"view_sort_new = started,name\n"
|
||||
"view_sort_current = started,name\n"
|
||||
|
||||
"view_add = stopped\n"
|
||||
"view_filter = stopped,stopped\n"
|
||||
"view_filter = stopped,not=$d.get_state=\n"
|
||||
"view_filter_on = stopped,start,stop\n"
|
||||
"view_sort_new = stopped,name\n"
|
||||
"view_sort_current = stopped,name\n"
|
||||
|
||||
"view_add = complete\n"
|
||||
"view_filter = complete,complete\n"
|
||||
"view_filter = complete,d.get_complete=\n"
|
||||
"view_filter_on = complete,hash_done,finished\n"
|
||||
"view_sort_new = complete,state_changed\n"
|
||||
"view_sort_current = complete,state_changed_reverse\n"
|
||||
|
||||
"view_add = incomplete\n"
|
||||
"view_filter = incomplete,incomplete\n"
|
||||
"view_filter = incomplete,not=$d.get_complete=\n"
|
||||
"view_filter_on = incomplete,hash_done,finished\n"
|
||||
"view_sort_new = incomplete,state_changed\n"
|
||||
"view_sort_current = incomplete,state_changed_reverse\n"
|
||||
|
||||
// The hashing view does not include stopped torrents.
|
||||
"view_add = hashing\n"
|
||||
"view_filter = hashing,hashing\n"
|
||||
"view_filter = hashing,d.get_hashing=\n"
|
||||
"view_filter_on = hashing,hash_queued,hash_removed,hash_done\n"
|
||||
"view_sort_new = hashing,state_changed\n"
|
||||
"view_sort_current = hashing,state_changed\n"
|
||||
|
||||
"view_add = seeding\n"
|
||||
"view_filter = seeding,started,complete\n"
|
||||
"view_filter = seeding,\"and=d.get_state=,d.get_complete=\"\n"
|
||||
"view_filter_on = seeding,start,stop\n"
|
||||
"view_sort_new = seeding,state_changed\n"
|
||||
"view_sort_current = seeding,state_changed_reverse\n"
|
||||
|
||||
+24
-8
@@ -102,6 +102,8 @@ public:
|
||||
typedef const torrent::Object (*peer_slot) (Command*, torrent::Peer*, const torrent::Object&);
|
||||
typedef const torrent::Object (*tracker_slot) (Command*, torrent::Tracker*, const torrent::Object&);
|
||||
|
||||
typedef const torrent::Object (*download_pair_slot) (Command*, core::Download*, core::Download*, const torrent::Object&);
|
||||
|
||||
static const int target_generic = 0;
|
||||
static const int target_any = 1;
|
||||
static const int target_download = 2;
|
||||
@@ -110,6 +112,8 @@ public:
|
||||
static const int target_file = 5;
|
||||
static const int target_file_itr = 6;
|
||||
|
||||
static const int target_download_pair = 7;
|
||||
|
||||
Command() {}
|
||||
virtual ~Command() {}
|
||||
|
||||
@@ -118,18 +122,30 @@ protected:
|
||||
void operator = (const Command&);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
template <typename T1 = void, typename T2 = void>
|
||||
struct target_type_id {
|
||||
// Nothing here, so we cause an error.
|
||||
};
|
||||
|
||||
template <> struct target_type_id<Command::generic_slot> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<Command::any_slot> { static const int value = Command::target_any; };
|
||||
template <> struct target_type_id<Command::download_slot> { static const int value = Command::target_download; };
|
||||
template <> struct target_type_id<Command::peer_slot> { static const int value = Command::target_peer; };
|
||||
template <> struct target_type_id<Command::tracker_slot> { static const int value = Command::target_tracker; };
|
||||
template <> struct target_type_id<Command::file_slot> { static const int value = Command::target_file; };
|
||||
template <> struct target_type_id<Command::file_itr_slot> { static const int value = Command::target_file_itr; };
|
||||
template <> struct target_type_id<Command::generic_slot> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<Command::any_slot> { static const int value = Command::target_any; };
|
||||
template <> struct target_type_id<Command::download_slot> { static const int value = Command::target_download; };
|
||||
template <> struct target_type_id<Command::peer_slot> { static const int value = Command::target_peer; };
|
||||
template <> struct target_type_id<Command::tracker_slot> { static const int value = Command::target_tracker; };
|
||||
template <> struct target_type_id<Command::file_slot> { static const int value = Command::target_file; };
|
||||
template <> struct target_type_id<Command::file_itr_slot> { static const int value = Command::target_file_itr; };
|
||||
|
||||
template <> struct target_type_id<Command::download_pair_slot> { static const int value = Command::target_download_pair; };
|
||||
|
||||
template <> struct target_type_id<> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<target_type> { static const int value = Command::target_any; };
|
||||
template <> struct target_type_id<core::Download*> { static const int value = Command::target_download; };
|
||||
template <> struct target_type_id<torrent::Peer*> { static const int value = Command::target_peer; };
|
||||
template <> struct target_type_id<torrent::Tracker*> { static const int value = Command::target_tracker; };
|
||||
template <> struct target_type_id<torrent::File*> { static const int value = Command::target_file; };
|
||||
template <> struct target_type_id<torrent::FileListIterator*> { static const int value = Command::target_file_itr; };
|
||||
|
||||
template <> struct target_type_id<core::Download*, core::Download*> { static const int value = Command::target_download_pair; };
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ struct command_map_data_type {
|
||||
Command::file_itr_slot m_fileItrSlot;
|
||||
Command::peer_slot m_peerSlot;
|
||||
Command::tracker_slot m_trackerSlot;
|
||||
|
||||
Command::download_slot m_downloadPairSlot;
|
||||
};
|
||||
|
||||
int m_flags;
|
||||
@@ -108,6 +110,7 @@ public:
|
||||
|
||||
iterator insert(key_type key, Command* variable, int flags, const char* parm, const char* doc);
|
||||
|
||||
// Make this a wrapper call to insert without extra fluff.
|
||||
template <typename T>
|
||||
void insert_type(key_type key, Command* variable, T targetSlot, int flags, const char* parm, const char* doc) {
|
||||
iterator itr = insert(key, variable, flags, parm, doc);
|
||||
@@ -132,12 +135,13 @@ private:
|
||||
};
|
||||
|
||||
inline target_type make_target() { return target_type((int)Command::target_generic, NULL); }
|
||||
inline target_type make_target(core::Download* target) { return target_type((int)Command::target_download, target); }
|
||||
inline target_type make_target(torrent::Peer* target) { return target_type((int)Command::target_peer, target); }
|
||||
inline target_type make_target(torrent::Tracker* target) { return target_type((int)Command::target_tracker, target); }
|
||||
inline target_type make_target(torrent::File* target) { return target_type((int)Command::target_file, target); }
|
||||
inline target_type make_target(torrent::FileListIterator* target) { return target_type((int)Command::target_file_itr, target); }
|
||||
inline target_type make_target(int type, void* target) { return target_type(type, target); }
|
||||
inline target_type make_target(int type, void* target1, void* target2) { return target_type(type, target1, target2); }
|
||||
|
||||
template <typename T>
|
||||
inline target_type make_target(T target) {
|
||||
return target_type((int)target_type_id<T>::value, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ inline void parse_command_multiple(target_type target, const char* fi
|
||||
bool parse_command_file(const std::string& path);
|
||||
const char* parse_command_name(const char* first, const char* last, std::string* dest);
|
||||
|
||||
inline torrent::Object
|
||||
parse_command_single(target_type target, const std::string& cmd) {
|
||||
return parse_command(target, cmd.c_str(), cmd.c_str() + cmd.size()).first;
|
||||
}
|
||||
|
||||
inline void
|
||||
parse_command_single_std(const std::string& cmd) {
|
||||
parse_command(make_target(), cmd.c_str(), cmd.c_str() + cmd.size());
|
||||
|
||||
Reference in New Issue
Block a user