diff --git a/rak/functional.h b/rak/functional.h index d21f7292..58530486 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -440,6 +440,7 @@ bind2nd(const Operation& op, const Type& val) { template class mem_fun0 { public: + typedef Ret result_type; typedef Ret (Object::*Function)(); mem_fun0() : m_object(NULL) {} @@ -457,6 +458,7 @@ private: template class const_mem_fun0 { public: + typedef Ret result_type; typedef Ret (Object::*Function)() const; const_mem_fun0() : m_object(NULL) {} @@ -474,6 +476,7 @@ private: template class mem_fun1 { public: + typedef Ret result_type; typedef Ret (Object::*Function)(Arg1); mem_fun1() : m_object(NULL) {} @@ -491,6 +494,7 @@ private: template class const_mem_fun1 { public: + typedef Ret result_type; typedef Ret (Object::*Function)(Arg1) const; const_mem_fun1() : m_object(NULL) {} @@ -508,6 +512,7 @@ private: template class mem_fun2 : public std::binary_function { public: + typedef Ret result_type; typedef Ret (Object::*Function)(Arg1, Arg2); typedef Object object_type; @@ -529,6 +534,7 @@ private: template class mem_fun3 { public: + typedef Ret result_type; typedef Ret (Object::*Function)(Arg1, Arg2, Arg3); mem_fun3() : m_object(NULL) {} diff --git a/src/display/canvas.cc b/src/display/canvas.cc index 7a7f440a..40fa5a5f 100644 --- a/src/display/canvas.cc +++ b/src/display/canvas.cc @@ -61,7 +61,7 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons attributes_list::const_iterator attrItr = attributes->begin(); while (first != last) { - if (attrItr != attributes->end() && attrItr->position() == first) { + if (attrItr != attributes->end() && attrItr->position() <= first) { attr = attrItr->attributes(); // Set colors or something. diff --git a/src/display/text_element_value.cc b/src/display/text_element_value.cc index 271b4f00..6666f1c3 100644 --- a/src/display/text_element_value.cc +++ b/src/display/text_element_value.cc @@ -36,6 +36,7 @@ #include "config.h" +#include "globals.h" #include "text_element_value.h" namespace display { @@ -56,8 +57,51 @@ TextElementValueBase::print(char* first, const char* last, Canvas::attributes_li else if (current.colors() != base.colors()) current.set_position(first); -// first += std::max(snprintf(first, last - first + 1, m_format, value(object)), 0); - first += std::max(snprintf(first, last - first, "%lld", value(object)), 0); + int64_t val = value(object); + + if (m_flags & flag_elapsed) + val = cachedTime.seconds() - val; + else if (m_flags & flag_remaining) + val = val - cachedTime.seconds(); + + if (m_flags & flag_usec) + val = rak::timer(val).seconds(); + + if (m_flags & flag_timer) { + if (val == 0) + first += std::max(snprintf(first, last - first + 1, "--:--:--"), 0); + else + first += std::max(snprintf(first, last - first + 1, "%2d:%02d:%02d", (int)(val / 3600), (int)((val / 60) % 60), (int)(val % 60)), 0); + + } else if (m_flags & flag_date) { + time_t t = val; + std::tm *u = std::gmtime(&t); + + if (u == NULL) + return first; + + first += std::max(snprintf(first, last - first + 1, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year)), 0); + + } else if (m_flags & flag_time) { + time_t t = val; + std::tm *u = std::gmtime(&t); + + if (u == NULL) + return first; + + first += std::max(snprintf(first, last - first + 1, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec), 0); + + } else if (m_flags & flag_kb) { + // Just use a default width of 5 for now. + first += std::max(snprintf(first, last - first + 1, "%5.1f", (double)val / (1 << 10)), 0); + + } else if (m_flags & flag_mb) { + // Just use a default width of 5 for now. + first += std::max(snprintf(first, last - first + 1, "%8.1f", (double)val / (1 << 20)), 0); + + } else { + first += std::max(snprintf(first, last - first + 1, "%lld", val), 0); + } if (current.position() != NULL) { attributes->push_back(current); diff --git a/src/display/text_element_value.h b/src/display/text_element_value.h index 2829c261..3394d8f8 100644 --- a/src/display/text_element_value.h +++ b/src/display/text_element_value.h @@ -46,33 +46,38 @@ namespace display { class TextElementValueBase : public TextElement { public: - static const extent_type max_format_length = 12; + static const int flag_normal = (1 << 0); + static const int flag_timer = (1 << 1); + static const int flag_date = (1 << 2); + static const int flag_time = (1 << 3); + + static const int flag_kb = (1 << 4); + static const int flag_mb = (1 << 5); + + static const int flag_elapsed = (1 << 8); + static const int flag_remaining = (1 << 9); + static const int flag_usec = (1 << 10); + + int flags() const { return m_flags; } + void set_flags(int flags) { m_flags = flags; } int attributes() const { return m_attributes; } void set_attributes(int a) { m_attributes = a; } - void set_format(const char* f); - virtual char* print(char* first, const char* last, Canvas::attributes_list* attributes, void* object); protected: virtual int64_t value(void* object) = 0; + int m_flags; int m_attributes; - char m_format[max_format_length]; }; -inline void -TextElementValueBase::set_format(const char* f) { - std::strncpy(m_format, f, max_format_length); - m_format[max_format_length - 1] = '\0'; -} - class TextElementValue : public TextElementValueBase { public: - TextElementValue(int64_t value, int attributes = Attributes::a_invalid) : m_value(value) { + TextElementValue(int64_t value, int flags = flag_normal, int attributes = Attributes::a_invalid) : m_value(value) { + m_flags = flags; m_attributes = attributes; - set_format("%lld"); } int64_t value() const { return m_value; } @@ -86,15 +91,33 @@ private: int64_t m_value; }; +template +class TextElementValueSlot0 : public TextElementValueBase { +public: + typedef typename slot_type::result_type result_type; + + TextElementValueSlot0(const slot_type& slot, int flags = flag_normal, int attributes = Attributes::a_invalid) : m_slot(slot) { + m_flags = flags; + m_attributes = attributes; + } + +private: + virtual extent_type max_length() { return 12; } + + virtual int64_t value(void* object) { return m_slot(); } + + slot_type m_slot; +}; + template class TextElementValueSlot : public TextElementValueBase { public: typedef typename slot_type::argument_type arg1_type; typedef typename slot_type::result_type result_type; - TextElementValueSlot(const slot_type& slot, int attributes = Attributes::a_invalid) : m_slot(slot) { + TextElementValueSlot(const slot_type& slot, int flags = flag_normal, int attributes = Attributes::a_invalid) : m_slot(slot) { + m_flags = flags; m_attributes = attributes; - set_format("%lld"); } private: @@ -112,10 +135,16 @@ private: slot_type m_slot; }; +template +inline TextElementValueSlot0* +text_element_value_void(const slot_type& slot, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { + return new TextElementValueSlot0(slot, flags, attributes); +} + template inline TextElementValueSlot* -text_element_value_slot(const slot_type& slot, int attributes = Attributes::a_invalid) { - return new TextElementValueSlot(slot, attributes); +text_element_value_slot(const slot_type& slot, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) { + return new TextElementValueSlot(slot, flags, attributes); } } diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index fcd7cf27..d0462bf4 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -66,47 +66,6 @@ WindowPeerInfo::redraw() { m_canvas->erase(); int y = 0; - char buffer[256]; - char* position; - - torrent::Download* d = m_download->download(); - - m_canvas->print(0, y++, "Hash: %s", rak::transform_hex(d->info_hash()).c_str()); - m_canvas->print(0, y++, "Id: %s", rak::copy_escape_html(d->local_id()).c_str()); - m_canvas->print(0, y++, "Chunks: %u / %u * %u", d->chunks_done(), d->chunks_total(), d->chunks_size()); - - y++; - - position = print_date(buffer, buffer + 256, static_cast(d->creation_date())); - m_canvas->print(0, y++, "Created: %s", buffer); - - position = print_timer(buffer, buffer + 256, static_cast(m_download->variable()->get_value("state_changed"))); - m_canvas->print(0, y++, "State Changed: %s", buffer); - - y++; - - m_canvas->print(0, y++, "Connection Type: %s ( %s / %s )", - m_download->variable()->get("connection_current").as_string().c_str(), - m_download->variable()->get("connection_seed").as_string().c_str(), - m_download->variable()->get("connection_leech").as_string().c_str()); - m_canvas->print(0, y++, "Priority: %u", torrent::download_priority(*m_download->download())); - - m_canvas->print(0, y++, "Directory: %s", m_download->variable_string("directory").c_str()); - m_canvas->print(0, y++, "Tied to file: %s", m_download->variable_string("tied_to_file").c_str()); - - y++; - - // Temporary. -// m_canvas->print(0, y++, "SndBuf: %u", torrent::connection_manager()->send_buffer_size()); -// m_canvas->print(0, y++, "RcvBuf: %u", torrent::connection_manager()->receive_buffer_size()); - - m_canvas->print(0, y++, "Memory Usage: %llu MB", torrent::chunk_manager()->memory_usage() / (1 << 20)); - m_canvas->print(0, y++, "Max Memory Usage: %llu MB", torrent::chunk_manager()->max_memory_usage() / (1 << 20)); - - m_canvas->print(0, y++, "Free Diskspace: %llu MB", m_download->download()->free_diskspace() / (1 << 20)); - m_canvas->print(0, y++, "Safe Diskspace: %llu MB", torrent::chunk_manager()->safe_free_diskspace() / (1 << 20)); - - y++; if (*m_focus == m_list->end()) { m_canvas->print(0, y++, "No peer in focus"); diff --git a/src/ui/download.cc b/src/ui/download.cc index 209ca616..92f8cd3b 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -104,22 +106,22 @@ inline ElementBase* Download::create_menu() { ElementMenu* element = new ElementMenu; - element->push_back("Peer List", + element->push_back("Peer list", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_PEER_LIST), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_PEER_LIST)); element->push_back("Info", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_INFO), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_INFO)); - element->push_back("File List", + element->push_back("File list", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_FILE_LIST), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_FILE_LIST)); - element->push_back("Tracker List", + element->push_back("Tracker kist", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRACKER_LIST), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRACKER_LIST)); - element->push_back("Chunks Seen", + element->push_back("Chunks seen", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_CHUNKS_SEEN), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_CHUNKS_SEEN)); - element->push_back("Transfer List", + element->push_back("Transfer list", sigc::bind(sigc::mem_fun(this, &Download::activate_display_focus), DISPLAY_TRANSFER_LIST), sigc::bind(sigc::mem_fun(this, &Download::activate_display_menu), DISPLAY_TRANSFER_LIST)); @@ -137,14 +139,43 @@ Download::create_info() { // Get these bindings with some kind of string map. element->push_column("Name:", display::text_element_string_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::name)))); - element->push_column("Local Id:", display::text_element_string_slot(std::mem_fun(&core::Download::local_id_escaped))); - element->push_column("Info Hash:", display::text_element_string_slot(std::mem_fun(&core::Download::info_hash_hex))); + element->push_column("Local id:", display::text_element_string_slot(std::mem_fun(&core::Download::local_id_escaped))); + element->push_column("Info hash:", display::text_element_string_slot(std::mem_fun(&core::Download::info_hash_hex))); + element->push_column("Created:", + display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::creation_date)), + display::TextElementValueBase::flag_date), " ", + display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::creation_date)), + display::TextElementValueBase::flag_time)); element->push_back(""); element->push_column("Directory:", display::text_element_string_slot(rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir)))); - element->push_column("Tied to File:", display::text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"))); + element->push_column("Tied to file:", display::text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"))); - element->push_column("Priority:", display::text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), "priority"))); + element->push_back(""); + element->push_column("Chunks:", + display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::chunks_done))), " / ", + display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::chunks_total))), " * ", + display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::chunks_size)))); + element->push_column("Priority:", display::text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), "priority"))); + + element->push_column("State changed:", display::text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), "state_changed"), + display::TextElementValueBase::flag_timer | display::TextElementValueBase::flag_elapsed)); + + element->push_back(""); + element->push_column("Memory usage:", display::text_element_value_void(rak::make_mem_fun(torrent::chunk_manager(), &torrent::ChunkManager::memory_usage), + display::TextElementValueBase::flag_mb), " MB"); + element->push_column("Max memory usage:", display::text_element_value_void(rak::make_mem_fun(torrent::chunk_manager(), &torrent::ChunkManager::max_memory_usage), + display::TextElementValueBase::flag_mb), " MB"); + element->push_column("Free diskspace:", display::text_element_value_slot(rak::on(std::mem_fun(&core::Download::c_download), std::mem_fun(&torrent::Download::free_diskspace)), + display::TextElementValueBase::flag_mb), " MB"); + element->push_column("Safe diskspace:", display::text_element_value_void(rak::make_mem_fun(torrent::chunk_manager(), &torrent::ChunkManager::safe_free_diskspace), + display::TextElementValueBase::flag_mb), " MB"); + + element->push_back(""); + element->push_column("Send buffer:", display::text_element_value_void(rak::make_mem_fun(torrent::connection_manager(), &torrent::ConnectionManager::send_buffer_size), + display::TextElementValueBase::flag_kb), " KB"); + element->push_column("Receive buffer:", display::text_element_value_void(rak::make_mem_fun(torrent::connection_manager(), &torrent::ConnectionManager::receive_buffer_size), + display::TextElementValueBase::flag_kb), " KB"); element->set_column_width(element->column_width() + 1); diff --git a/src/ui/element_text.cc b/src/ui/element_text.cc index bfb05eb1..6f800319 100644 --- a/src/ui/element_text.cc +++ b/src/ui/element_text.cc @@ -117,4 +117,57 @@ ElementText::push_column(text_element_wrapper entry1, text_element_wrapper entry push_back(list); } +void +ElementText::push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3) { + m_columnWidth = std::max(entry1.m_element->max_length(), m_columnWidth); + + display::TextElementList* list = new display::TextElementList; + list->set_column(m_column); + list->set_column_width(&m_columnWidth); + + list->push_back(entry1.m_element); + list->push_back(entry2.m_element); + list->push_back(entry3.m_element); + + push_back(list); +} + +void +ElementText::push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3, text_element_wrapper entry4) { + m_columnWidth = std::max(entry1.m_element->max_length(), m_columnWidth); + + display::TextElementList* list = new display::TextElementList; + list->set_column(m_column); + list->set_column_width(&m_columnWidth); + + list->push_back(entry1.m_element); + list->push_back(entry2.m_element); + list->push_back(entry3.m_element); + list->push_back(entry4.m_element); + + push_back(list); +} + +void +ElementText::push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3, text_element_wrapper entry4, + text_element_wrapper entry5, text_element_wrapper entry6) { + m_columnWidth = std::max(entry1.m_element->max_length(), m_columnWidth); + + display::TextElementList* list = new display::TextElementList; + list->set_column(m_column); + list->set_column_width(&m_columnWidth); + + list->push_back(entry1.m_element); + list->push_back(entry2.m_element); + list->push_back(entry3.m_element); + list->push_back(entry4.m_element); + list->push_back(entry5.m_element); + list->push_back(entry6.m_element); + + push_back(list); +} + } diff --git a/src/ui/element_text.h b/src/ui/element_text.h index 35d7689b..05c5a098 100644 --- a/src/ui/element_text.h +++ b/src/ui/element_text.h @@ -73,6 +73,16 @@ public: void push_column(text_element_wrapper entry1, text_element_wrapper entry2); + void push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3); + + void push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3, text_element_wrapper entry4); + + void push_column(text_element_wrapper entry1, text_element_wrapper entry2, + text_element_wrapper entry3, text_element_wrapper entry4, + text_element_wrapper entry5, text_element_wrapper entry6a); + void set_column(unsigned int column) { m_column = column; } extent_type column_width() const { return m_columnWidth; }