* 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:
rakshasa
2008-03-16 13:55:40 +00:00
parent 8cc7c8430d
commit f9ff1cf5ac
9 changed files with 134 additions and 88 deletions
+62 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -41
View File
@@ -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();
}
+1 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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; };
}
+9 -5
View File
@@ -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);
}
}
+5
View File
@@ -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());