* Changed ViewSort::less(...) to operator().

* Added a "last changed" paramter to ViewManager::sort(...) which is
checked, if the ViewDownloads's last_changed timer was poked withing
that timeframe it won't update.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@676 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-04-27 21:38:02 +00:00
parent 8ae5e51a0f
commit 02a0510439
14 changed files with 190 additions and 71 deletions
+1
View File
@@ -427,6 +427,7 @@ interface address.
<varlistentry>
<term>ip = <replaceable>a.b.c.d</replaceable></term>
<term>ip = <replaceable>hostname</replaceable></term>
<listitem><para>
Set the address reported to the tracker.
+4 -2
View File
@@ -27,11 +27,13 @@
#schedule = untied_directory,5,5,stop_untied=
# The ip address reported to the tracker.
#ip = rakshasa
#ip = 127.0.0.1
#ip = rakshasa.no
# The ip address the listening socket and outgoing connections is
# bound to.
#bind = rakshasa
#bind = 127.0.0.1
#bind = rakshasa.no
# Port range to use for listening.
#port_range = 6890-6999
+4 -2
View File
@@ -76,6 +76,8 @@ ViewDownloads::initialize(const std::string& name, core::DownloadList* list) {
m_size = 0;
m_focus = 0;
set_last_changed(rak::timer());
std::for_each(m_list->begin(), m_list->end(), std::bind1st(std::mem_fun(&ViewDownloads::received_insert), this));
m_list->slot_map_insert()[key] = sigc::mem_fun(this, &ViewDownloads::received_insert);
@@ -111,9 +113,9 @@ struct view_downloads_compare : std::binary_function<Download*, Download*, bool>
bool operator () (Download* d1, Download* d2) const {
for (ViewDownloads::sort_list::const_iterator itr = m_sort.begin(), last = m_sort.end(); itr != last; ++itr)
if ((*itr)->less(d1, d2))
if ((**itr)(d1, d2))
return true;
else if ((*itr)->less(d2, d1))
else if ((**itr)(d2, d1))
return false;
// Since we're testing equivalence, return false if we're
+17 -9
View File
@@ -37,11 +37,9 @@
// Provides a filtered and sorted list of downloads that can be
// updated auto-magically.
//
// We don't worry about std::vector's insert/erase performance as it
// get's called so often, better with cache locality.
//
// Do we want to be able to modify the underlying DownloadList from
// here?
// We don't worry about std::vector's insert/erase performance as the
// elements get accessed often but not modified, better with cache
// locality.
//
// ViewDownloads::m_size indicates the number of Download's that
// remain visible, e.g. has not been filtered out. The Download's that
@@ -54,9 +52,11 @@
#include <memory>
#include <string>
#include <vector>
//#include <rak/timer.h>
#include <rak/timer.h>
#include <sigc++/signal.h>
#include "globals.h"
namespace core {
class Download;
@@ -116,6 +116,15 @@ public:
void filter();
void set_filter(const filter_list& s) { m_filter = s; }
// 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.
//
// Currently initialized to rak::timer(), though perhaps we should
// use cachedTimer.
rak::timer last_changed() const { return m_lastChanged; }
void set_last_changed(const rak::timer& t = ::cachedTime) { m_lastChanged = t; }
// Don't connect any slots until after initialize else it get's
// triggered when adding the Download's in DownloadList.
signal_type& signal_changed() { return m_signalChanged; }
@@ -143,8 +152,7 @@ private:
filter_list m_filter;
// Timer, last changed.
rak::timer m_lastChanged;
signal_type m_signalChanged;
};
@@ -152,7 +160,7 @@ class ViewSort {
public:
virtual ~ViewSort() {}
virtual bool less(Download* d1, Download* d2) const = 0;
virtual bool operator () (Download* d1, Download* d2) const = 0;
};
class ViewFilter {
+12 -6
View File
@@ -40,6 +40,8 @@
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include "globals.h"
#include "download.h"
#include "view_downloads.h"
#include "view_manager.h"
@@ -48,7 +50,7 @@ namespace core {
class ViewSortName : public ViewSort {
public:
virtual bool less(Download* d1, Download* d2) const {
virtual bool operator () (Download* d1, Download* d2) const {
return d1->download()->name() < d2->download()->name();
}
};
@@ -58,7 +60,7 @@ public:
ViewSortVariable(const std::string& name, const std::string& value) :
m_name(name), m_value(value) {}
virtual bool less(Download* d1, Download* d2) const {
virtual bool operator () (Download* d1, Download* d2) const {
return
d1->variable()->get_string(m_name) == m_value &&
d2->variable()->get_string(m_name) != m_value;
@@ -74,7 +76,7 @@ public:
ViewSortVariableValue(const std::string& name) :
m_name(name) {}
virtual bool less(Download* d1, Download* d2) const {
virtual bool operator () (Download* d1, Download* d2) const {
return d1->variable()->get_value(m_name) < d2->variable()->get_value(m_name);
}
@@ -87,8 +89,8 @@ public:
ViewSortReverse(ViewSort* s) : m_sort(s) {}
~ViewSortReverse() { delete m_sort; }
virtual bool less(Download* d1, Download* d2) const {
return m_sort->less(d2, d1);
virtual bool operator () (Download* d1, Download* d2) const {
return (*m_sort)(d2, d1);
}
private:
@@ -126,6 +128,7 @@ ViewManager::ViewManager(DownloadList* dl) :
m_sort["state_changed_reverse"] = new ViewSortReverse(new ViewSortVariableValue("state_changed"));
m_filter["started"] = new ViewFilterVariableValue("state", 1);
m_filter["stopped"] = new ViewFilterVariableValue("state", 0);
}
void
@@ -180,9 +183,12 @@ ViewManager::build_sort_list(const sort_args& args) {
}
void
ViewManager::sort(const std::string& name) {
ViewManager::sort(const std::string& name, uint32_t timeout) {
iterator viewItr = find_throw(name);
if ((*viewItr)->last_changed() + rak::timer::from_seconds(timeout) > cachedTime)
return;
// Should we rename sort, or add a seperate function?
(*viewItr)->filter();
+5 -1
View File
@@ -92,7 +92,11 @@ public:
iterator find(const std::string& name);
iterator find_throw(const std::string& name);
void sort(const std::string& name);
// If ViewDownloads::last_changed() is less than 'timeout' seconds
// ago, don't sort.
//
// 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 sort_args& sort);
void set_sort_current(const std::string& name, const sort_args& sort);
+17 -9
View File
@@ -48,24 +48,32 @@
namespace display {
WindowDownloadList::WindowDownloadList(core::ViewDownloads* l) :
Window(new Canvas, true),
m_view(l) {
m_connChanged = m_view->signal_changed().connect(sigc::mem_fun(*this, &Window::mark_dirty));
}
WindowDownloadList::~WindowDownloadList() {
m_connChanged.disconnect();
}
void
WindowDownloadList::set_view(core::ViewDownloads* l) {
m_view = l;
m_connChanged.disconnect();
if (m_view != NULL)
m_connChanged = m_view->signal_changed().connect(sigc::mem_fun(*this, &Window::mark_dirty));
}
void
WindowDownloadList::redraw() {
m_slotSchedule(this, (cachedTime + rak::timer::from_seconds(1)).round_seconds());
m_canvas->erase();
if (m_view->empty() || m_canvas->get_width() < 5)
if (m_view == NULL)
return;
m_canvas->print(0, 0, "%s", ("[View: " + m_view->name() + "]").c_str());
if (m_view->empty() || m_canvas->get_width() < 5 || m_canvas->get_height() < 2)
return;
typedef std::pair<core::ViewDownloads::iterator, core::ViewDownloads::iterator> Range;
@@ -81,7 +89,7 @@ WindowDownloadList::redraw() {
if (range.second != m_view->end())
++range.second;
int pos = 0;
int pos = 1;
while (range.first != range.second) {
char buffer[m_canvas->get_width()];
+3 -1
View File
@@ -51,11 +51,13 @@ namespace display {
class WindowDownloadList : public Window {
public:
WindowDownloadList(core::ViewDownloads* l);
WindowDownloadList() : Window(new Canvas, true), m_view(NULL) {}
~WindowDownloadList();
virtual void redraw();
void set_view(core::ViewDownloads* l);
private:
core::ViewDownloads* m_view;
+23 -2
View File
@@ -163,11 +163,32 @@ main(int argc, char** argv) {
initialize_option_handler(control);
control->variable()->process_command("view_add = main");
control->variable()->process_command("view_filter = main,started");
control->variable()->process_command("view_sort_new = main,name");
control->variable()->process_command("view_sort_current = main,name");
// Changing these will bork the scheduler.
control->variable()->process_command("view_add = started");
control->variable()->process_command("view_filter = started,started");
control->variable()->process_command("view_sort_new = started,name");
control->variable()->process_command("view_sort_current = started,name");
control->variable()->process_command("view_add = stopped");
control->variable()->process_command("view_filter = stopped,stopped");
control->variable()->process_command("view_sort_new = stopped,name");
control->variable()->process_command("view_sort_current = stopped,name");
control->variable()->process_command("view_add = finished");
//control->variable()->process_command("view_filter = finished,stopped");
control->variable()->process_command("view_sort_new = finished,state_changed");
control->variable()->process_command("view_sort_current = finished,state_changed_reverse");
control->variable()->process_command("schedule = view_main,10,10,view_sort=main,30");
control->variable()->process_command("schedule = view_started,10,10,view_sort=started");
control->variable()->process_command("schedule = view_stopped,10,10,view_sort=stopped");
control->variable()->process_command("schedule = view_finished,10,10,view_sort=finished,30");
//control->variable()->process_command("schedule = scheduler,10,10,download_scheduler=");
// Changing these will bork the (non-existant) scheduler.
control->variable()->process_command("view_add = scheduler");
control->variable()->process_command("view_sort_new = scheduler,state_changed"); // add started?
control->variable()->process_command("view_sort_current = scheduler,state_changed");
+49 -24
View File
@@ -183,6 +183,52 @@ apply_tos(const std::string& arg) {
throw torrent::input_error("Invalid TOS identifier.");
}
void
apply_view_filter(Control* control, const std::string& arg) {
rak::split_iterator_t<std::string> itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
if (name.empty())
throw torrent::input_error("First argument must be a string.");
core::ViewManager::filter_args filterArgs;
while (++itr != rak::split_iterator(arg)) {
filterArgs.push_back(rak::trim(*itr));
if (filterArgs.back().empty())
throw torrent::input_error("One of the arguments is empty.");
}
control->view_manager()->set_filter(name, filterArgs);
}
void
apply_view_sort(Control* control, const std::string& arg) {
rak::split_iterator_t<std::string> itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
++itr;
if (name.empty())
throw torrent::input_error("First argument must be a string.");
// Need some generic tools for this, rather than hacking up
// something every time...
std::string arg1;
int32_t value = 0;
if (itr != rak::split_iterator(arg) && !(arg1 = *itr).empty()) {
char* endPtr;
if ((value = strtol(arg1.c_str(), &endPtr, 0)) < 0 || *endPtr != '\0')
throw torrent::input_error("Second argument must be a value.");
}
control->view_manager()->sort(name, value);
}
void
apply_view_sort_current(Control* control, const std::string& arg) {
rak::split_iterator_t<std::string> itr = rak::split_iterator(arg, ',');
@@ -225,27 +271,6 @@ apply_view_sort_new(Control* control, const std::string& arg) {
control->view_manager()->set_sort_new(name, sortArgs);
}
void
apply_view_filter(Control* control, const std::string& arg) {
rak::split_iterator_t<std::string> itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
if (name.empty())
throw torrent::input_error("First argument must be a string.");
core::ViewManager::filter_args filterArgs;
while (++itr != rak::split_iterator(arg)) {
filterArgs.push_back(rak::trim(*itr));
if (filterArgs.back().empty())
throw torrent::input_error("One of the arguments is empty.");
}
control->view_manager()->set_filter(name, filterArgs);
}
void
apply_download_scheduler(core::Scheduler* scheduler, __UNUSED const std::string& arg) {
scheduler->update();
@@ -302,12 +327,12 @@ initialize_option_handler(Control* c) {
rak::mem_fn(control->variable(), &utils::VariableMap::process_file_nothrow)));
variables->insert("view_add", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->view_manager(), &core::ViewManager::insert_throw)));
variables->insert("view_sort", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->view_manager(), &core::ViewManager::sort)));
variables->insert("view_filter", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_filter, c)));
variables->insert("view_sort", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort, c)));
variables->insert("view_sort_new", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_new, c)));
variables->insert("view_sort_current", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_current, c)));
variables->insert("view_filter", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_filter, c)));
variables->insert("schedule", new utils::VariableStringSlot(rak::value_fn(std::string()),
rak::mem_fn<const std::string&>(c->command_scheduler(), &CommandScheduler::parse)));
variables->insert("schedule_remove", new utils::VariableStringSlot(rak::value_fn(std::string()),
+34 -3
View File
@@ -83,12 +83,15 @@ DownloadList::DownloadList(Control* c) :
m_control(c),
m_bindings(new input::Bindings)
{
m_view = *c->view_manager()->find_throw("main");
m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList(m_view);
m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList();
m_uiArray[DISPLAY_LOG] = new ElementLogComplete(&m_control->core()->get_log_complete());
m_windowLog = new WLog(&m_control->core()->get_log_important());
receive_change_view("main");
if (m_view == NULL)
throw torrent::internal_error("View \"main\" must be present to initialize the main display.");
m_taskUpdate.set_slot(rak::mem_fn(this, &DownloadList::task_update)),
setup_keys();
@@ -183,11 +186,13 @@ DownloadList::disable_display() {
void
DownloadList::receive_next() {
m_view->next_focus();
m_view->set_last_changed();
}
void
DownloadList::receive_prev() {
m_view->prev_focus();
m_view->set_last_changed();
}
void
@@ -365,6 +370,26 @@ DownloadList::receive_download_erased(core::Download* d) {
receive_next();
}
void
DownloadList::receive_change_view(const std::string& name) {
core::ViewManager::iterator itr = m_control->view_manager()->find(name);
if (itr == m_control->view_manager()->end()) {
m_control->core()->push_log("Could not find view \"" + name + "\".");
return;
}
m_view = *itr;
m_view->sort();
ElementDownloadList* ui = dynamic_cast<ElementDownloadList*>(m_uiArray[DISPLAY_DOWNLOAD_LIST]);
if (ui == NULL)
throw torrent::internal_error("DownloadList::receive_change_view(...) could not cast ui.");
ui->set_view(m_view);
}
void
DownloadList::task_update() {
m_windowLog->receive_update();
@@ -393,6 +418,12 @@ DownloadList::setup_keys() {
(*m_bindings)[KEY_RIGHT] = sigc::mem_fun(*this, &DownloadList::receive_view_download);
(*m_bindings)['l'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_LOG);
(*m_bindings)['1'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "main");
(*m_bindings)['2'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "started");
(*m_bindings)['3'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "stopped");
(*m_bindings)['4'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "finished");
(*m_bindings)['5'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change_view), "incomplete");
m_uiArray[DISPLAY_LOG]->get_bindings()[' '] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_change), DISPLAY_DOWNLOAD_LIST);
}
+2
View File
@@ -137,6 +137,8 @@ private:
void receive_download_erased(core::Download* d);
void receive_change_view(const std::string& name);
void task_update();
void setup_keys();
+15 -7
View File
@@ -38,7 +38,6 @@
#include <stdexcept>
#include "display/window_download_list.h"
#include "input/manager.h"
#include "control.h"
@@ -46,11 +45,6 @@
namespace ui {
ElementDownloadList::ElementDownloadList(core::ViewDownloads* l) :
m_window(NULL),
m_view(l) {
}
void
ElementDownloadList::activate(Control* c, MItr mItr) {
if (m_window != NULL)
@@ -58,7 +52,10 @@ ElementDownloadList::activate(Control* c, MItr mItr) {
c->input()->push_front(&m_bindings);
*mItr = m_window = new WDownloadList(m_view);
m_window = new WDownloadList();
m_window->set_view(m_view);
*mItr = m_window;
}
void
@@ -72,4 +69,15 @@ ElementDownloadList::disable(Control* c) {
m_window = NULL;
}
void
ElementDownloadList::set_view(core::ViewDownloads* l) {
m_view = l;
if (m_window == NULL)
return;
m_window->set_view(l);
m_window->mark_dirty();
}
}
+4 -5
View File
@@ -38,6 +38,7 @@
#define RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H
#include "core/download_list.h"
#include "display/window_download_list.h"
#include "element_base.h"
@@ -47,21 +48,19 @@ namespace core {
class ViewDownloads;
}
namespace display {
class WindowDownloadList;
}
namespace ui {
class ElementDownloadList : public ElementBase {
public:
typedef display::WindowDownloadList WDownloadList;
ElementDownloadList(core::ViewDownloads* l);
ElementDownloadList() : m_window(NULL), m_view(NULL) {}
void activate(Control* c, MItr mItr);
void disable(Control* c);
void set_view(core::ViewDownloads* l);
private:
WDownloadList* m_window;
core::ViewDownloads* m_view;