/list command, can join the room with J (cannot sort, search or filter yet,...

/list command, can join the room with J (cannot sort, search or filter yet, and lacks some information)
parent 2b58f653
This diff is collapsed.
...@@ -125,19 +125,19 @@ class Tab(object): ...@@ -125,19 +125,19 @@ class Tab(object):
raise NotImplementedError raise NotImplementedError
def on_input(self, key): def on_input(self, key):
raise NotImplementedError pass
def on_lose_focus(self): def on_lose_focus(self):
""" """
called when this tab loses the focus. called when this tab loses the focus.
""" """
raise NotImplementedError pass
def on_gain_focus(self): def on_gain_focus(self):
""" """
called when this tab gains the focus. called when this tab gains the focus.
""" """
raise NotImplementedError pass
def add_message(self): def add_message(self):
""" """
...@@ -146,25 +146,25 @@ class Tab(object): ...@@ -146,25 +146,25 @@ class Tab(object):
FormTab, where text is not intented to be appened), it returns False. FormTab, where text is not intented to be appened), it returns False.
If the tab can, it returns True If the tab can, it returns True
""" """
raise NotImplementedError return False
def on_scroll_down(self): def on_scroll_down(self):
""" """
Defines what happens when we scrol down Defines what happens when we scrol down
""" """
raise NotImplementedError pass
def on_scroll_up(self): def on_scroll_up(self):
""" """
Defines what happens when we scrol down Defines what happens when we scrol down
""" """
raise NotImplementedError pass
def on_info_win_size_changed(self): def on_info_win_size_changed(self):
""" """
Called when the window with the informations is resized Called when the window with the informations is resized
""" """
raise NotImplementedError pass
def just_before_refresh(self): def just_before_refresh(self):
""" """
...@@ -172,13 +172,13 @@ class Tab(object): ...@@ -172,13 +172,13 @@ class Tab(object):
Particularly useful to move the cursor at the Particularly useful to move the cursor at the
correct position. correct position.
""" """
raise NotImplementedError pass
def on_close(self): def on_close(self):
""" """
Called when the tab is to be closed Called when the tab is to be closed
""" """
raise NotImplementedError pass
class InfoTab(Tab): class InfoTab(Tab):
""" """
...@@ -933,6 +933,102 @@ class ConversationTab(ChatTab): ...@@ -933,6 +933,102 @@ class ConversationTab(ChatTab):
def on_close(self): def on_close(self):
return return
class MucListTab(Tab):
"""
A tab listing rooms from a specific server, displaying various information,
scrollable, and letting the user join them, etc
"""
def __init__(self, core, server):
Tab.__init__(self, core)
self._color_state = theme.COLOR_TAB_NORMAL
self.name = server
self.upper_message = windows.Topic()
columns = ('node-part','name', 'users')
self.list_header = windows.ColumnHeaderWin(columns)
self.listview = windows.ListWin(columns)
self.tab_win = windows.GlobalInfoBar()
self.default_help_message = windows.HelpText("“j”: join room. “i”: information")
self.input = self.default_help_message
self.key_func["KEY_DOWN"] = self.listview.move_cursor_down
self.key_func["KEY_UP"] = self.listview.move_cursor_up
self.key_func["/"] = self.on_slash
self.key_func['j'] = self.join_selected
self.key_func['J'] = self.join_selected_no_focus
self.resize()
def refresh(self, tabs, informations, roster):
self.upper_message.refresh('Chatroom list on server %s' % self.name)
self.list_header.refresh()
self.listview.refresh()
self.tab_win.refresh(tabs, tabs[0])
self.input.refresh()
def resize(self):
Tab.resize(self)
self.upper_message.resize(1, self.width, 0, 0, self.core.stdscr)
column_size = {'node-part': (self.width-5)//4,
'name': (self.width-5)//4*3,
'users': 5}
self.list_header.resize_columns(column_size)
self.list_header.resize(1, self.width, 1, 0, self.core.stdscr)
self.listview.resize_columns(column_size)
self.listview.resize(self.height-4, self.width, 2, 0, self.core.stdscr)
self.tab_win.resize(1, self.width, self.height-2, 0, self.core.stdscr)
self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
def on_slash(self):
"""
'/' is pressed, activate the input
"""
curses.curs_set(1)
self.input = windows.CommandInput("", self.reset_help_message, self.execute_slash_command)
self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
self.input.do_command("/") # we add the slash
def join_selected_no_focus(self):
return
def join_selected(self):
jid = self.listview.get_selected_row()['jid']
self.core.command_join(jid)
def reset_help_message(self, _=None):
curses.curs_set(0)
self.input = self.default_help_message
return True
def execute_slash_command(self, txt):
if txt.startswith('/'):
self.core.execute(txt)
return self.reset_help_message()
def get_color_state(self):
return theme.COLOR_TAB_NORMAL
def set_color_state(self, color):
pass
def get_name(self):
return self.name
def on_input(self, key):
res = self.input.do_command(key)
if res:
return True
if key in self.key_func:
return self.key_func[key]()
def on_lose_focus(self):
self._color_state = theme.COLOR_TAB_NORMAL
def on_gain_focus(self):
self._color_state = theme.COLOR_TAB_CURRENT
curses.curs_set(0)
def get_color_state(self):
return self._color_state
def diffmatch(search, string): def diffmatch(search, string):
""" """
Use difflib and a loop to check if search_pattern can Use difflib and a loop to check if search_pattern can
......
...@@ -41,7 +41,7 @@ from contact import Contact, Resource ...@@ -41,7 +41,7 @@ from contact import Contact, Resource
from roster import RosterGroup, roster from roster import RosterGroup, roster
from message import Line from message import Line
from tab import MIN_WIDTH, MIN_HEIGHT from tabs import MIN_WIDTH, MIN_HEIGHT
from sleekxmpp.xmlstream.stanzabase import JID from sleekxmpp.xmlstream.stanzabase import JID
...@@ -55,17 +55,7 @@ class Win(object): ...@@ -55,17 +55,7 @@ class Win(object):
def _resize(self, height, width, y, x, parent_win): def _resize(self, height, width, y, x, parent_win):
self.height, self.width, self.x, self.y = height, width, x, y self.height, self.width, self.x, self.y = height, width, x, y
# try:
self._win = curses.newwin(height, width, y, x) self._win = curses.newwin(height, width, y, x)
# except:
# # When resizing in a too little height (less than 3 lines)
# # We don't need to resize the window, since this size
# # just makes no sense
# # Just don't crash when this happens.
# # (°> also, a penguin
# # //\
# # V_/_
# return
def _refresh(self): def _refresh(self):
self._win.noutrefresh() self._win.noutrefresh()
...@@ -404,10 +394,6 @@ class MucInfoWin(InfoWin): ...@@ -404,10 +394,6 @@ class MucInfoWin(InfoWin):
self.addstr(txt, curses.color_pair(theme.COLOR_INFORMATION_BAR)) self.addstr(txt, curses.color_pair(theme.COLOR_INFORMATION_BAR))
class TextWin(Win): class TextWin(Win):
"""
Just keep ONE single window for the text area and rewrite EVERYTHING
on each change. (thanks weechat :o)
"""
def __init__(self): def __init__(self):
Win.__init__(self) Win.__init__(self)
...@@ -1278,3 +1264,122 @@ class ContactInfoWin(Win): ...@@ -1278,3 +1264,122 @@ class ContactInfoWin(Win):
elif isinstance(selected_row, Resource): elif isinstance(selected_row, Resource):
self.draw_contact_info(selected_row) self.draw_contact_info(selected_row)
self._refresh() self._refresh()
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):
self._columns = columns # a tuple with the name of the columns
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
def resize(self, height, width, y, x, stdscr):
self._resize(height, width, y, x, stdscr)
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
"""
pass # TODO
def add_lines(self, lines):
"""
Append some lines at the end of the list
"""
if not lines:
return
self.lines += lines
self.refresh()
def get_selected_row(self):
"""
Return the tuple representing the selected row
"""
if self._selected_row:
return self.lines[self._selected_row]
return None
def refresh(self):
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:
try:
txt = line[col] or ''
except (KeyError):
txt = ''
size = self._columns_sizes[col]
txt += ' ' * (size-len(txt))
if not txt:
continue
if line is self.lines[self._selected_row]:
self.addstr(y, x, txt[:size], curses.color_pair(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
class ColumnHeaderWin(Win):
"""
A class displaying the column's names
"""
def __init__(self, columns):
self._columns = columns
self._columns_sizes = {}
def resize_columns(self, dic):
self._columns_sizes = dic
def resize(self, height, width, y, x, stdscr):
self._resize(height, width, y, x, stdscr)
def refresh(self):
with g_lock:
self._win.erase()
x = 0
for col in self._columns:
txt = col
size = self._columns_sizes[col]
txt += ' ' * (size-len(txt))
self.addstr(0, x, txt, curses.color_pair(theme.COLOR_STATUS_UNAVAILABLE))
x += size
self._refresh()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment