Merge branch 'master' into ipv6

This commit is contained in:
rakshasa
2016-08-29 18:19:45 +09:00
34 changed files with 1033 additions and 643 deletions
+56 -40
View File
@@ -5,12 +5,12 @@
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -41,90 +41,106 @@
#include <termios.h>
#include <torrent/exceptions.h>
#include "rpc/parse_commands.h"
#include "canvas.h"
namespace display {
bool Canvas::m_isInitialized = false;
bool Canvas::m_isDaemon = false;
Canvas::Canvas(int x, int y, int width, int height) :
m_window(newwin(height, width, y, x)) {
Canvas::Canvas(int x, int y, int width, int height) {
if (!m_isDaemon) {
m_window = newwin(height, width, y, x);
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
if (m_window == NULL)
throw torrent::internal_error("Could not allocate ncurses canvas.");
}
}
void
Canvas::resize(int x, int y, int w, int h) {
wresize(m_window, h, w);
mvwin(m_window, y, x);
if (!m_isDaemon) {
wresize(m_window, h, w);
mvwin(m_window, y, x);
}
}
void
Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes) {
move(x, y);
if (!m_isDaemon) {
move(x, y);
attr_t org_attr;
short org_pair;
wattr_get(m_window, &org_attr, &org_pair, NULL);
attr_t org_attr;
short org_pair;
wattr_get(m_window, &org_attr, &org_pair, NULL);
attributes_list::const_iterator attrItr = attributes->begin();
wattr_set(m_window, Attributes::a_normal, Attributes::color_default, NULL);
attributes_list::const_iterator attrItr = attributes->begin();
wattr_set(m_window, Attributes::a_normal, Attributes::color_default, NULL);
while (first != last) {
const char* next = last;
while (first != last) {
const char* next = last;
if (attrItr != attributes->end()) {
next = attrItr->position();
if (attrItr != attributes->end()) {
next = attrItr->position();
if (first >= next) {
wattr_set(m_window, attrItr->attributes(), attrItr->colors(), NULL);
++attrItr;
if (first >= next) {
wattr_set(m_window, attrItr->attributes(), attrItr->colors(), NULL);
++attrItr;
}
}
print("%.*s", next - first, first);
first = next;
}
print("%.*s", next - first, first);
first = next;
// Reset the color.
wattr_set(m_window, org_attr, org_pair, NULL);
}
// Reset the color.
wattr_set(m_window, org_attr, org_pair, NULL);
}
void
Canvas::initialize() {
if (m_isInitialized)
return;
m_isDaemon = rpc::call_command_value("system.daemon");
m_isInitialized = true;
initscr();
raw();
noecho();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
if (!m_isDaemon) {
initscr();
raw();
noecho();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
}
}
void
Canvas::cleanup() {
if (!m_isInitialized)
return;
m_isInitialized = false;
noraw();
endwin();
if (!m_isDaemon) {
noraw();
endwin();
}
}
std::pair<int, int>
Canvas::term_size() {
struct winsize ws;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0)
return std::pair<int, int>(ws.ws_col, ws.ws_row);
else
return std::pair<int, int>(80, 24);
if (!m_isDaemon) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0)
return std::pair<int, int>(ws.ws_col, ws.ws_row);
}
return std::pair<int, int>(80, 24);
}
}
+41 -34
View File
@@ -5,12 +5,12 @@
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -49,37 +49,37 @@ public:
typedef std::vector<Attributes> attributes_list;
Canvas(int x = 0, int y = 0, int width = 0, int height = 0);
~Canvas() { delwin(m_window); }
~Canvas() { if (!m_isDaemon) { delwin(m_window); } }
void refresh() { wnoutrefresh(m_window); }
static void refresh_std() { wnoutrefresh(stdscr); }
void redraw() { redrawwin(m_window); }
static void redraw_std() { redrawwin(stdscr); }
void refresh() { if (!m_isDaemon) { wnoutrefresh(m_window); } }
static void refresh_std() { if (!m_isDaemon) { wnoutrefresh(stdscr); } }
void redraw() { if (!m_isDaemon) { redrawwin(m_window); } }
static void redraw_std() { if (!m_isDaemon) { redrawwin(stdscr); } }
void resize(int w, int h) { wresize(m_window, h, w); }
void resize(int w, int h) { if (!m_isDaemon) { wresize(m_window, h, w); } }
void resize(int x, int y, int w, int h);
static void resize_term(int x, int y) { resizeterm(y, x); }
static void resize_term(std::pair<int, int> dim) { resizeterm(dim.second, dim.first); }
static void resize_term(int x, int y) { if (!m_isDaemon) { resizeterm(y, x); } }
static void resize_term(std::pair<int, int> dim) { if (!m_isDaemon) { resizeterm(dim.second, dim.first); } }
unsigned int get_x() { int x, __UNUSED y; getyx(m_window, y, x); return x; }
unsigned int get_y() { int x, y; getyx(m_window, y, x); return y; }
unsigned int get_x() { int x, __UNUSED y; if (!m_isDaemon) { getyx(m_window, y, x); } else { x=1; } return x; }
unsigned int get_y() { int x, y; if (!m_isDaemon) { getyx(m_window, y, x); } else { y=1; } return y; }
unsigned int width() { int x, __UNUSED y; getmaxyx(m_window, y, x); return x; }
unsigned int height() { int x, y; getmaxyx(m_window, y, x); return y; }
unsigned int width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { x=80; } return x; }
unsigned int height() { int x, y; if (!m_isDaemon) { getmaxyx(m_window, y, x); } else { y=24; } return y; }
void move(unsigned int x, unsigned int y) { wmove(m_window, y, x); }
void move(unsigned int x, unsigned int y) { if (!m_isDaemon) { wmove(m_window, y, x); } }
chtype get_background() { return getbkgd(m_window); }
void set_background(chtype c) { return wbkgdset(m_window, c); }
chtype get_background() { chtype bg=0; if (!m_isDaemon) { bg=getbkgd(m_window); } return bg; }
void set_background(chtype c) { if (!m_isDaemon) { return wbkgdset(m_window, c); } }
void erase() { werase(m_window); }
static void erase_std() { werase(stdscr); }
void erase() { if (!m_isDaemon) { werase(m_window); } }
static void erase_std() { if (!m_isDaemon) { werase(stdscr); } }
void print_border(chtype ls, chtype rs,
chtype ts, chtype bs,
chtype tl, chtype tr,
chtype bl, chtype br) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); }
chtype bl, chtype br) { if (!m_isDaemon) { wborder(m_window, ls, rs, ts, bs, tl, tr, bl, br); } }
// The format string is non-const, but that will not be a problem
// since the string shall always be a C string choosen at
@@ -90,29 +90,32 @@ public:
void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes);
void print_char(const chtype ch) { waddch(m_window, ch); }
void print_char(unsigned int x, unsigned int y, const chtype ch) { mvwaddch(m_window, y, x, ch); }
void print_char(const chtype ch) { if (!m_isDaemon) { waddch(m_window, ch); } }
void print_char(unsigned int x, unsigned int y, const chtype ch) { if (!m_isDaemon) { mvwaddch(m_window, y, x, ch); } }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { mvwchgat(m_window, y, x, n, attr, color, NULL); }
void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { if (!m_isDaemon) { mvwchgat(m_window, y, x, n, attr, color, NULL); } }
void set_default_attributes(int attr) { (void)wattrset(m_window, attr); }
void set_default_attributes(int attr) { if (!m_isDaemon) { (void)wattrset(m_window, attr); } }
// Initialize stdscr.
static void initialize();
static void cleanup();
static int get_screen_width() { int x, __UNUSED y; getmaxyx(stdscr, y, x); return x; }
static int get_screen_height() { int x, y; getmaxyx(stdscr, y, x); return y; }
static int get_screen_width() { int x, __UNUSED y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { x=80; } return x; }
static int get_screen_height() { int x, y; if (!m_isDaemon) { getmaxyx(stdscr, y, x); } else { y=24;} return y; }
static std::pair<int, int> term_size();
static void do_update() { doupdate(); }
static void do_update() { if (!m_isDaemon) { doupdate(); } }
static bool daemon() { return m_isDaemon; }
private:
Canvas(const Canvas&);
void operator = (const Canvas&);
static bool m_isInitialized;
static bool m_isDaemon;
WINDOW* m_window;
};
@@ -121,19 +124,23 @@ inline void
Canvas::print(const char* str, ...) {
va_list arglist;
va_start(arglist, str);
vw_printw(m_window, const_cast<char*>(str), arglist);
va_end(arglist);
if (!m_isDaemon) {
va_start(arglist, str);
vw_printw(m_window, const_cast<char*>(str), arglist);
va_end(arglist);
}
}
inline void
Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
va_list arglist;
va_start(arglist, str);
wmove(m_window, y, x);
vw_printw(m_window, const_cast<char*>(str), arglist);
va_end(arglist);
if (!m_isDaemon) {
va_start(arglist, str);
wmove(m_window, y, x);
vw_printw(m_window, const_cast<char*>(str), arglist);
va_end(arglist);
}
}
}
+64 -2
View File
@@ -133,7 +133,7 @@ print_download_title(char* first, char* last, core::Download* d) {
}
char*
print_download_info(char* first, char* last, core::Download* d) {
print_download_info_full(char* first, char* last, core::Download* d) {
if (!d->download()->info()->is_open())
first = print_buffer(first, last, "[CLOSED] ");
else if (!d->download()->info()->is_active())
@@ -177,7 +177,7 @@ print_download_info(char* first, char* last, core::Download* d) {
first = print_buffer(first, last , "]");
if (first > last)
throw torrent::internal_error("print_download_info(...) wrote past end of the buffer.");
throw torrent::internal_error("print_download_info_full(...) wrote past end of the buffer.");
return first;
}
@@ -218,6 +218,68 @@ print_download_status(char* first, char* last, core::Download* d) {
return first;
}
char*
print_download_column_compact(char* first, char* last) {
first = print_buffer(first, last, " %-64.64s", "Name");
first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio| Misc ");
if (first > last)
throw torrent::internal_error("print_download_column_compact(...) wrote past end of the buffer.");
return first;
}
char*
print_download_info_compact(char* first, char* last, core::Download* d) {
first = print_buffer(first, last, " %-64.64s", d->info()->name().c_str());
first = print_buffer(first, last, "|");
if (!d->download()->info()->is_open())
first = print_buffer(first, last, " CLOSED ");
else if (!d->download()->info()->is_active())
first = print_buffer(first, last, " OPEN ");
else
first = print_buffer(first, last, " ");
first = print_buffer(first, last, "| %7.1f MB ", (double)d->download()->bytes_done() / (double)(1 << 20));
first = print_buffer(first, last, "| %7.1f MB ", (double)d->download()->file_list()->size_bytes() / (double)(1 << 20));
first = print_buffer(first, last, "|");
if (d->is_done())
first = print_buffer(first, last, " 100%% ");
else if (d->is_open())
first = print_buffer(first, last, " %2u%% ",(d->download()->file_list()->completed_chunks() * 100) / d->download()->file_list()->size_chunks());
else
first = print_buffer(first, last, " ");
first = print_buffer(first, last, "| %6.1f KB ", (double)d->info()->up_rate()->rate() / (1 << 10));
first = print_buffer(first, last, "| %6.1f KB ", (double)d->info()->down_rate()->rate() / (1 << 10));
first = print_buffer(first, last, "| %7.1f MB ", (double)d->info()->up_rate()->total() / (1 << 20));
first = print_buffer(first, last, "| ");
if (d->download()->info()->is_active() && !d->is_done())
first = print_download_time_left(first, last, d);
else
first = print_buffer(first, last, " ");
first = print_buffer(first, last, "| %4.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
first = print_buffer(first, last, "| %c%c",
rpc::call_command_string("d.tied_to_file", rpc::make_target(d)).empty() ? ' ' : 'T',
rpc::call_command_value("d.ignore_commands", rpc::make_target(d)) == 0 ? ' ' : 'I',
(double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
if (d->priority() != 2)
first = print_buffer(first, last, " %s", rpc::call_command_string("d.priority_str", rpc::make_target(d)).c_str());
if (!d->bencode()->get_key("rtorrent").get_key_string("throttle_name").empty())
first = print_buffer(first, last , " %s", rpc::call_command_string("d.throttle_name", rpc::make_target(d)).c_str());
if (first > last)
throw torrent::internal_error("print_download_info_compact(...) wrote past end of the buffer.");
return first;
}
char*
print_download_time_left(char* first, char* last, core::Download* d) {
uint32_t rate = d->info()->down_rate()->rate();
+5 -1
View File
@@ -66,8 +66,12 @@ char* print_ddhhmm(char* first, char* last, time_t t);
char* print_ddmmyyyy(char* first, char* last, time_t t);
char* print_download_title(char* first, char* last, core::Download* d);
char* print_download_info(char* first, char* last, core::Download* d);
char* print_download_info_full(char* first, char* last, core::Download* d);
char* print_download_status(char* first, char* last, core::Download* d);
char* print_download_column_compact(char* first, char* last);
char* print_download_info_compact(char* first, char* last, core::Download* d);
char* print_download_time_left(char* first, char* last, core::Download* d);
char* print_download_percentage_done(char* first, char* last, core::Download* d);
+42 -13
View File
@@ -40,6 +40,7 @@
#include "core/download.h"
#include "core/view.h"
#include "rpc/parse_commands.h"
#include "canvas.h"
#include "globals.h"
@@ -85,12 +86,24 @@ WindowDownloadList::redraw() {
if (m_view->empty_visible() || m_canvas->width() < 5 || m_canvas->height() < 2)
return;
int layout_height;
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
if (layout_name == "full") {
layout_height = 3;
} else if (layout_name == "compact") {
layout_height = 1;
} else {
m_canvas->print(0, 0, "INVALID ui.torrent_list.layout '%s'", layout_name.c_str());
return;
}
typedef std::pair<core::View::iterator, core::View::iterator> Range;
Range range = rak::advance_bidirectional(m_view->begin_visible(),
m_view->focus() != m_view->end_visible() ? m_view->focus() : m_view->begin_visible(),
m_view->end_visible(),
m_canvas->height() / 3);
m_canvas->height() / layout_height);
// Make sure we properly fill out the last lines so it looks like
// there are more torrents, yet don't hide it if we got the last one
@@ -99,22 +112,38 @@ WindowDownloadList::redraw() {
++range.second;
int pos = 1;
char buffer[m_canvas->width() + 1];
char* last = buffer + m_canvas->width() - 2 + 1;
while (range.first != range.second) {
char buffer[m_canvas->width() + 1];
char* last = buffer + m_canvas->width() - 2 + 1;
// Add a proper 'column info' method.
if (layout_name == "compact") {
print_download_column_compact(buffer, last);
print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
print_download_info(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
m_canvas->set_default_attributes(A_BOLD);
m_canvas->print(0, pos++, " %s", buffer);
}
print_download_status(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
if (layout_name == "full") {
while (range.first != range.second) {
print_download_title(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
print_download_info_full(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
print_download_status(buffer, last, *range.first);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
++range.first;
}
range.first++;
}
} else {
while (range.first != range.second) {
print_download_info_compact(buffer, last, *range.first);
m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
range.first++;
}
}
}
}
+1 -1
View File
@@ -66,7 +66,7 @@ WindowDownloadStatusbar::redraw() {
char buffer[m_canvas->width()];
char* last = buffer + m_canvas->width() - 2;
print_download_info(buffer, last, m_download);
print_download_info_full(buffer, last, m_download);
m_canvas->print(0, 0, "%s", buffer);
snprintf(buffer, last - buffer, "Peers: %i(%i) Min/Max: %i/%i Slots: U:%i/%i D:%i/%i U/I/C/A: %i/%i/%i/%i Unchoked: %u/%u Failed: %i",