summaryrefslogtreecommitdiff
path: root/src/windows/list.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/list.py')
-rw-r--r--src/windows/list.py237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/windows/list.py b/src/windows/list.py
new file mode 100644
index 00000000..3cfb8af5
--- /dev/null
+++ b/src/windows/list.py
@@ -0,0 +1,237 @@
+"""
+Windows relevant for the listing tabs, not much else
+"""
+
+import logging
+log = logging.getLogger(__name__)
+
+import curses
+
+from . import Win, g_lock
+from theming import to_curses_attr, get_theme
+
+
+class ListWin(Win):
+ """
+ A list (with no depth, so not for the roster) that can be
+ scrolled up and down, with one selected line at a time
+ """
+ def __init__(self, columns, with_headers=True):
+ Win.__init__(self)
+ self._columns = columns # a dict {'column_name': tuple_index}
+ self._columns_sizes = {} # a dict {'column_name': size}
+ self.sorted_by = (None, None) # for example: ('name', '↑')
+ self.lines = [] # a list of dicts
+ self._selected_row = 0
+ self._starting_pos = 0 # The column number from which we start the refresh
+
+ @property
+ def pos(self):
+ if len(self.lines) > self.height:
+ return len(self.lines)
+ else:
+ return 0
+
+ def empty(self):
+ """
+ emtpy the list and reset some important values as well
+ """
+ self.lines = []
+ self._selected_row = 0
+ self._starting_pos = 0
+
+ def resize_columns(self, dic):
+ """
+ Resize the width of the columns
+ """
+ self._columns_sizes = dic
+
+ def sort_by_column(self, col_name, asc=True):
+ """
+ Sort the list by the given column, ascendant or descendant
+ """
+ if not col_name:
+ return
+ elif asc:
+ self.lines.sort(key=lambda x: x[self._columns[col_name]])
+ else:
+ self.lines.sort(key=lambda x: x[self._columns[col_name]],
+ reverse=True)
+ self.refresh()
+ curses.doupdate()
+
+ def add_lines(self, lines):
+ """
+ Append some lines at the end of the list
+ """
+ if not lines:
+ return
+ self.lines.extend(lines)
+
+ def set_lines(self, lines):
+ """
+ Set the lines to another list
+ """
+ if not lines:
+ return
+ self.lines = lines
+
+ def get_selected_row(self):
+ """
+ Return the tuple representing the selected row
+ """
+ if self._selected_row is not None and self.lines:
+ return self.lines[self._selected_row]
+ return None
+
+ def refresh(self):
+ log.debug('Refresh: %s', self.__class__.__name__)
+ with g_lock:
+ self._win.erase()
+ lines = self.lines[self._starting_pos:self._starting_pos+self.height]
+ for y, line in enumerate(lines):
+ x = 0
+ for col in self._columns.items():
+ try:
+ txt = line[col[1]] or ''
+ except KeyError:
+ txt = ''
+ size = self._columns_sizes[col[0]]
+ txt += ' ' * (size-len(txt))
+ if not txt:
+ continue
+ if line is self.lines[self._selected_row]:
+ self.addstr(y, x, txt[:size], to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ else:
+ self.addstr(y, x, txt[:size])
+ x += size
+ self._refresh()
+
+ def move_cursor_down(self):
+ """
+ Move the cursor Down
+ """
+ if not self.lines:
+ return
+ if self._selected_row < len(self.lines) - 1:
+ self._selected_row += 1
+ while self._selected_row >= self._starting_pos + self.height:
+ self._starting_pos += self.height // 2
+ if self._starting_pos < 0:
+ self._starting_pos = 0
+ return True
+
+ def move_cursor_up(self):
+ """
+ Move the cursor Up
+ """
+ if not self.lines:
+ return
+ if self._selected_row > 0:
+ self._selected_row -= 1
+ while self._selected_row < self._starting_pos:
+ self._starting_pos -= self.height // 2
+ return True
+
+ def scroll_down(self):
+ if not self.lines:
+ return
+ self._selected_row += self.height
+ if self._selected_row > len(self.lines) - 1:
+ self._selected_row = len(self.lines) -1
+ while self._selected_row >= self._starting_pos + self.height:
+ self._starting_pos += self.height // 2
+ if self._starting_pos < 0:
+ self._starting_pos = 0
+ return True
+
+ def scroll_up(self):
+ if not self.lines:
+ return
+ self._selected_row -= self.height + 1
+ if self._selected_row < 0:
+ self._selected_row = 0
+ while self._selected_row < self._starting_pos:
+ self._starting_pos -= self.height // 2
+ return True
+
+class ColumnHeaderWin(Win):
+ """
+ A class displaying the column's names
+ """
+ def __init__(self, columns):
+ Win.__init__(self)
+ self._columns = columns
+ self._columns_sizes = {}
+ self._column_sel = ''
+ self._column_order = ''
+ self._column_order_asc = False
+
+ def resize_columns(self, dic):
+ self._columns_sizes = dic
+
+ def get_columns(self):
+ return self._columns
+
+ def refresh(self):
+ log.debug('Refresh: %s', self.__class__.__name__)
+ with g_lock:
+ self._win.erase()
+ x = 0
+ for col in self._columns:
+ txt = col
+ if col in self._column_order:
+ if self._column_order_asc:
+ txt += get_theme().CHAR_COLUMN_ASC
+ else:
+ txt += get_theme().CHAR_COLUMN_DESC
+ #⇓⇑↑↓⇧⇩▲▼
+ size = self._columns_sizes[col]
+ txt += ' ' * (size-len(txt))
+ if col in self._column_sel:
+ self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER_SEL))
+ else:
+ self.addstr(0, x, txt, to_curses_attr(get_theme().COLOR_COLUMN_HEADER))
+ x += size
+ self._refresh()
+
+ def sel_column(self, dic):
+ self._column_sel = dic
+
+ def get_sel_column(self):
+ return self._column_sel
+
+ def set_order(self, order):
+ self._column_order = self._column_sel
+ self._column_order_asc = order
+
+ def get_order(self):
+ if self._column_sel == self._column_order:
+ return self._column_order_asc
+ else:
+ return False
+
+ def sel_column_left(self):
+ if self._column_sel in self._columns:
+ index = self._columns.index(self._column_sel)
+ if index > 1:
+ index = index -1
+ else:
+ index = 0
+ else:
+ index = 0
+ self._column_sel = self._columns[index]
+ self.refresh()
+
+ def sel_column_right(self):
+ if self._column_sel in self._columns:
+ index = self._columns.index(self._column_sel)
+ if index < len(self._columns)-2:
+ index = index +1
+ else:
+ index = len(self._columns) -1
+ else:
+ index = len(self._columns) - 1
+ self._column_sel = self._columns[index]
+ self.refresh()
+