diff --git a/src/core/download_list.h b/src/core/download_list.h index d4acd56c..5ac7bdf7 100644 --- a/src/core/download_list.h +++ b/src/core/download_list.h @@ -38,6 +38,8 @@ public: using Base::const_iterator; using Base::reverse_iterator; using Base::const_reverse_iterator; + using Base::value_type; + using Base::pointer; using Base::begin; using Base::end; diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index 956b774e..dab07994 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -31,10 +31,15 @@ namespace display { -WindowDownloadList::WindowDownloadList(DList* l, DList::iterator* f) : +WindowDownloadList::WindowDownloadList(DList* l) : Window(new Canvas, true), - m_list(l), - m_focus(f) { + m_list(l) { + + m_connChanged = m_list->signal_changed().connect(sigc::mem_fun(*this, &Window::mark_dirty)); +} + +WindowDownloadList::~WindowDownloadList() { + m_connChanged.disconnect(); } void @@ -43,13 +48,13 @@ WindowDownloadList::redraw() { m_canvas->erase(); - if (m_list->empty()) + if (m_list->base().empty()) return; typedef std::pair Range; Range range = rak::advance_bidirectional(m_list->begin(), - *m_focus != m_list->end() ? *m_focus : m_list->begin(), + m_list->get_focus() != m_list->end() ? m_list->get_focus() : m_list->begin(), m_list->end(), m_canvas->get_height() / 3); @@ -65,19 +70,19 @@ WindowDownloadList::redraw() { torrent::Download& d = (*range.first)->get_download(); m_canvas->print(0, pos++, "%c %s", - range.first == *m_focus ? '*' : ' ', + range.first == m_list->get_focus() ? '*' : ' ', d.get_name().c_str()); if ((*range.first)->is_open() && (*range.first)->is_done()) m_canvas->print(0, pos++, "%c Torrent: Done %10.1f MiB Rate: %5.1f / %5.1f KiB Uploaded: %.1f MiB", - range.first == *m_focus ? '*' : ' ', + range.first == m_list->get_focus() ? '*' : ' ', (double)d.get_bytes_total() / (double)(1 << 20), (double)d.get_rate_up() / 1024.0, (double)d.get_rate_down() / 1024.0, (double)d.get_bytes_up() / (double)(1 << 20)); else m_canvas->print(0, pos++, "%c Torrent: %6.1f / %6.1f MiB Rate: %5.1f / %5.1f KiB Uploaded: %.1f MiB", - range.first == *m_focus ? '*' : ' ', + range.first == m_list->get_focus() ? '*' : ' ', (double)d.get_bytes_done() / (double)(1 << 20), (double)d.get_bytes_total() / (double)(1 << 20), (double)d.get_rate_up() / 1024.0, @@ -85,7 +90,7 @@ WindowDownloadList::redraw() { (double)d.get_bytes_up() / (double)(1 << 20)); m_canvas->print(0, pos++, "%c %s", - range.first == *m_focus ? '*' : ' ', + range.first == m_list->get_focus() ? '*' : ' ', print_download_status(*range.first).c_str()); ++range.first; diff --git a/src/display/window_download_list.h b/src/display/window_download_list.h index 845a11c6..deb626b0 100644 --- a/src/display/window_download_list.h +++ b/src/display/window_download_list.h @@ -23,22 +23,28 @@ #ifndef RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H #define RTORRENT_DISPLAY_WINDOW_DOWNLOAD_LIST_H +#include + #include "window.h" + #include "core/download_list.h" +#include "utils/list_focus.h" namespace display { class WindowDownloadList : public Window { public: - typedef core::DownloadList DList; + typedef utils::ListFocus DList; - WindowDownloadList(DList* l, DList::iterator* focus); + WindowDownloadList(DList* l); + ~WindowDownloadList(); - virtual void redraw(); + virtual void redraw(); private: - DList* m_list; - DList::iterator* m_focus; + DList* m_list; + + sigc::connection m_connChanged; }; } diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index a1e0e48a..fc89957f 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -58,11 +58,13 @@ DownloadList::DownloadList(Control* c) : m_taskUpdate(sigc::mem_fun(*this, &DownloadList::task_update)), m_uiDownload(NULL), - m_focus(c->get_core().get_download_list().end()), + + m_downloadList(&c->get_core().get_download_list()), + m_control(c), m_bindings(new input::Bindings) { - m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList(&m_control->get_core().get_download_list(), &m_focus); + m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList(&m_downloadList); m_uiArray[DISPLAY_LOG] = new ElementLogComplete(&m_control->get_core().get_log_complete()); m_windowLog = new WLog(&m_control->get_core().get_log_important()); @@ -158,22 +160,12 @@ DownloadList::disable_display() { void DownloadList::receive_next() { - if (m_focus != m_control->get_core().get_download_list().end()) - ++m_focus; - else - m_focus = m_control->get_core().get_download_list().begin(); - - //mark_dirty(); + m_downloadList.inc_focus(); } void DownloadList::receive_prev() { - if (m_focus != m_control->get_core().get_download_list().begin()) - --m_focus; - else - m_focus = m_control->get_core().get_download_list().end(); - - //mark_dirty(); + m_downloadList.dec_focus(); } void @@ -185,26 +177,26 @@ DownloadList::receive_throttle(int t) { void DownloadList::receive_start_download() { - if (m_focus == m_control->get_core().get_download_list().end()) + if (m_downloadList.get_focus() == m_downloadList.end()) return; - m_control->get_core().start(*m_focus); + m_control->get_core().start(*m_downloadList.get_focus()); } void DownloadList::receive_stop_download() { - if (m_focus == m_control->get_core().get_download_list().end()) + if (m_downloadList.get_focus() == m_downloadList.end()) return; - if ((*m_focus)->get_download().is_active()) - m_control->get_core().stop(*m_focus); + if ((*m_downloadList.get_focus())->get_download().is_active()) + m_control->get_core().stop(*m_downloadList.get_focus()); else - m_focus = m_control->get_core().erase(m_focus); + m_downloadList.set_focus(m_control->get_core().erase(m_downloadList.get_focus())); } void DownloadList::receive_view_download() { - if (m_focus == m_control->get_core().get_download_list().end()) + if (m_downloadList.get_focus() == m_downloadList.end()) return; if (m_uiDownload != NULL) @@ -212,7 +204,7 @@ DownloadList::receive_view_download() { disable(); - m_uiDownload = new Download(*m_focus, m_control); + m_uiDownload = new Download(*m_downloadList.get_focus(), m_control); m_uiDownload->activate(); m_uiDownload->get_bindings()[KEY_LEFT] = sigc::mem_fun(*this, &DownloadList::receive_exit_download); diff --git a/src/ui/download_list.h b/src/ui/download_list.h index e49d8afa..722c7d00 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -27,6 +27,7 @@ #include "core/download_list.h" #include "utils/task.h" +#include "utils/list_focus.h" namespace input { class Bindings; @@ -58,7 +59,7 @@ public: typedef display::WindowStatusbar WStatus; typedef display::WindowTitle WTitle; - typedef core::DownloadList DList; + typedef utils::ListFocus DList; typedef sigc::slot1 SlotOpenUri; @@ -122,8 +123,7 @@ private: Download* m_uiDownload; - DList* m_list; - DList::iterator m_focus; + DList m_downloadList; Control* m_control; input::Bindings* m_bindings; diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc index eeb07d76..bb272700 100644 --- a/src/ui/element_download_list.cc +++ b/src/ui/element_download_list.cc @@ -31,11 +31,9 @@ namespace ui { -ElementDownloadList::ElementDownloadList(DList* l, DList::iterator* f) : +ElementDownloadList::ElementDownloadList(DList* l) : m_window(NULL), - m_list(l), - m_focus(f) { - + m_list(l) { } void @@ -45,7 +43,7 @@ ElementDownloadList::activate(Control* c, MItr mItr) { c->get_input().push_front(&m_bindings); - *mItr = m_window = new WDownloadList(m_list, m_focus); + *mItr = m_window = new WDownloadList(m_list); } void diff --git a/src/ui/element_download_list.h b/src/ui/element_download_list.h index 46daf482..d4064b41 100644 --- a/src/ui/element_download_list.h +++ b/src/ui/element_download_list.h @@ -24,6 +24,7 @@ #define RTORRENT_UI_ELEMENT_DOWNLOAD_LIST_H #include "core/download_list.h" +#include "utils/list_focus.h" #include "element_base.h" @@ -37,10 +38,10 @@ class Control; class ElementDownloadList : public ElementBase { public: - typedef display::WindowDownloadList WDownloadList; - typedef core::DownloadList DList; + typedef display::WindowDownloadList WDownloadList; + typedef utils::ListFocus DList; - ElementDownloadList(DList* l, DList::iterator* f); + ElementDownloadList(DList* l); void activate(Control* c, MItr mItr); void disable(Control* c); @@ -49,7 +50,6 @@ private: WDownloadList* m_window; DList* m_list; - DList::iterator* m_focus; }; } diff --git a/src/utils/list_focus.h b/src/utils/list_focus.h index d91023b8..07097c8a 100644 --- a/src/utils/list_focus.h +++ b/src/utils/list_focus.h @@ -27,54 +27,93 @@ namespace utils { +// Can't make this class inherit privately due to gcc PR 14258. + template -class ListFocus : private Base { +class ListFocus { public: - using Base::iterator; - using Base::const_iterator; - using Base::reverse_iterator; - using Base::const_reverse_iterator; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::reverse_iterator reverse_iterator; + typedef typename Base::const_reverse_iterator const_reverse_iterator; - using Base::value_type; + typedef typename Base::value_type value_type; + typedef sigc::signal0 Signal; - using Base::begin; - using Base::end; - using Base::rbegin; - using Base::rend; + ListFocus(Base* b = NULL) : m_base(b) { if (b) m_focus = b->end(); } - using Base::insert; - using Base::push_back; - using Base::push_front; + // Convinience functions, would have added more through using, but + // can't. + iterator begin() { return m_base->begin(); } + iterator end() { return m_base->end(); } + reverse_iterator rbegin() { return m_base->rbegin(); } + reverse_iterator rend() { return m_base->rend(); } - ListFocus() : m_focus(end()) {} + // Don't do erase on this object without making sure focus is right. + Base& base() { return *m_base; } - // Don't do erase on this object. - Base& get_list() { return m_list; } - typename iterator& get_focus() { return m_focus; } + iterator get_focus() { return m_focus; } + void set_focus(iterator itr) { m_focus = itr; m_signalChanged.emit(); } - typename iterator erase(typename iterator itr); - void remove(typename const value_type& v); + // These are looping increment/decrements. + iterator inc_focus(); + iterator dec_focus(); + + iterator erase(iterator itr); + void remove(const value_type& v); // Be careful with copying signals. + Signal& signal_changed() { return m_signalChanged; } private: - typename iterator m_focus; + Base* m_base; + iterator m_focus; + + Signal m_signalChanged; }; template typename ListFocus::iterator -ListFocus::erase(typename iterator itr) { - if (itr == m_focus) - return m_focus = Base::erase(itr); +ListFocus::inc_focus() { + if (m_focus != end()) + ++m_focus; else - return Base::erase(itr); + m_focus = begin(); + + m_signalChanged.emit(); + + return m_focus; +} + +template +typename ListFocus::iterator +ListFocus::dec_focus() { + if (m_focus != begin()) + --m_focus; + else + m_focus = end(); + + m_signalChanged.emit(); + + return m_focus; +} + +template +typename ListFocus::iterator +ListFocus::erase(iterator itr) { + if (itr == m_focus) + return m_focus = m_base->erase(itr); + else + return m_base->erase(itr); + + m_signalChanged.emit(); } template void -ListFocus::remove(typename const value_type& v) { - typename iterator first = begin(); - typename iterator last = end(); +ListFocus::remove(const value_type& v) { + iterator first = begin(); + iterator last = end(); while (first != last) if (*first == v)