summaryrefslogtreecommitdiff
path: root/poezio/core/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'poezio/core/core.py')
-rw-r--r--poezio/core/core.py278
1 files changed, 71 insertions, 207 deletions
diff --git a/poezio/core/core.py b/poezio/core/core.py
index 015515c0..f6985a56 100644
--- a/poezio/core/core.py
+++ b/poezio/core/core.py
@@ -44,6 +44,7 @@ from poezio.theming import get_theme
from poezio import keyboard, xdg
from poezio.core.completions import CompletionCore
+from poezio.core.tabs import Tabs
from poezio.core.commands import CommandCore
from poezio.core.handlers import HandlerCore
from poezio.core.structs import POSSIBLE_SHOW, DEPRECATED_ERRORS, \
@@ -94,8 +95,7 @@ class Core:
self.xml_tab = None
self.xml_buffer = TextBuffer()
- self.tabs = []
- self._current_tab_nb = 0
+ self.tabs = Tabs()
self.previous_tab_nb = 0
own_nick = config.get('default_nick')
@@ -398,8 +398,7 @@ class Core:
Called when the option create_gaps is changed.
Remove all gaptabs if switching from gaps to nogaps.
"""
- if value.lower() == "false":
- self.tabs = [tab for tab in self.tabs if tab]
+ self.tabs.update_gaps(value.lower() == "false")
def on_request_receipts_config_change(self, option, value):
"""
@@ -652,7 +651,7 @@ class Core:
except ValueError:
pass
else:
- if self.current_tab().nb == nb and config.get(
+ if self.tabs.current_tab.nb == nb and config.get(
'go_to_previous_tab_on_alt_number'):
self.go_to_previous_tab()
else:
@@ -706,9 +705,9 @@ class Core:
Messages are namedtuples of the form
('txt nick_color time str_time nickname user')
"""
- if not isinstance(self.current_tab(), tabs.ChatTab):
+ if not isinstance(self.tabs.current_tab, tabs.ChatTab):
return None
- return self.current_tab().get_conversation_messages()
+ return self.tabs.current_tab.get_conversation_messages()
def insert_input_text(self, text):
"""
@@ -821,7 +820,7 @@ class Core:
keyboard.continuation_keys_callback = None
cb(key)
else:
- self.current_tab().on_input(key, raw)
+ self.tabs.current_tab.on_input(key, raw)
def try_execute(self, line):
"""
@@ -829,7 +828,7 @@ class Core:
"""
line = '/' + line
try:
- self.current_tab().execute_command(line)
+ self.tabs.current_tab.execute_command(line)
except:
log.error('Execute failed (%s)', line, exc_info=True)
@@ -902,9 +901,9 @@ class Core:
conversation.
Returns False if the current tab is not a conversation tab
"""
- if not isinstance(self.current_tab(), tabs.ChatTab):
+ if not isinstance(self.tabs.current_tab, tabs.ChatTab):
return False
- self.current_tab().command_say(msg)
+ self.tabs.current_tab.command_say(msg)
return True
def invite(self, jid, room, reason=None):
@@ -970,15 +969,8 @@ class Core:
def get_tabs(self, cls=None):
"Get all the tabs of a type"
if cls is None:
- cls = tabs.Tab
- return [tab for tab in self.tabs if isinstance(tab, cls)]
-
- def current_tab(self):
- """
- returns the current room, the one we are viewing
- """
- self.current_tab_nb = self.current_tab_nb
- return self.tabs[self.current_tab_nb]
+ return self.tabs.get_tabs()
+ return self.tabs.by_class(cls)
def get_conversation_by_jid(self, jid, create=True, fallback_barejid=True):
"""
@@ -992,16 +984,16 @@ class Core:
jid = safeJID(jid)
# We first check if we have a static conversation opened
# with this precise resource
- conversation = self.get_tab_by_name(jid.full,
- tabs.StaticConversationTab)
+ conversation = self.tabs.by_name_and_class(jid.full,
+ tabs.StaticConversationTab)
if jid.bare == jid.full and not conversation:
- conversation = self.get_tab_by_name(jid.full,
- tabs.DynamicConversationTab)
+ conversation = self.tabs.by_name_and_class(
+ jid.full, tabs.DynamicConversationTab)
if not conversation and fallback_barejid:
# If not, we search for a conversation with the bare jid
- conversation = self.get_tab_by_name(jid.bare,
- tabs.DynamicConversationTab)
+ conversation = self.tabs.by_name_and_class(
+ jid.bare, tabs.DynamicConversationTab)
if not conversation:
if create:
# We create a dynamic conversation with the bare Jid if
@@ -1013,23 +1005,6 @@ class Core:
conversation = None
return conversation
- def get_tab_by_name(self, name, typ=None):
- """
- Get the tab with the given name.
- If typ is provided, return a tab of this type only
- """
- for tab in self.tabs:
- if tab.name == name:
- if (typ and isinstance(tab, typ)) or\
- not typ:
- return tab
- return None
-
- def get_tab_by_number(self, number):
- if 0 <= number < len(self.tabs):
- return self.tabs[number]
- return None
-
def add_tab(self, new_tab, focus=False):
"""
Appends the new_tab in the tab list and
@@ -1039,82 +1014,12 @@ class Core:
if focus:
self.command.win("%s" % new_tab.nb)
- def insert_tab_nogaps(self, old_pos, new_pos):
- """
- Move tabs without creating gaps
- old_pos: old position of the tab
- new_pos: desired position of the tab
- """
- tab = self.tabs[old_pos]
- if new_pos < old_pos:
- self.tabs.pop(old_pos)
- self.tabs.insert(new_pos, tab)
- elif new_pos > old_pos:
- self.tabs.insert(new_pos, tab)
- self.tabs.remove(tab)
- else:
- return False
- return True
-
- def insert_tab_gaps(self, old_pos, new_pos):
- """
- Move tabs and create gaps in the eventual remaining space
- old_pos: old position of the tab
- new_pos: desired position of the tab
- """
- tab = self.tabs[old_pos]
- target = None if new_pos >= len(self.tabs) else self.tabs[new_pos]
- if not target:
- if new_pos < len(self.tabs):
- old_tab = self.tabs[old_pos]
- self.tabs[new_pos], self.tabs[old_pos] = old_tab, tabs.GapTab(
- self)
- else:
- self.tabs.append(self.tabs[old_pos])
- self.tabs[old_pos] = tabs.GapTab(self)
- else:
- if new_pos > old_pos:
- self.tabs.insert(new_pos, tab)
- self.tabs[old_pos] = tabs.GapTab(self)
- elif new_pos < old_pos:
- self.tabs[old_pos] = tabs.GapTab(self)
- self.tabs.insert(new_pos, tab)
- else:
- return False
- i = self.tabs.index(tab)
- done = False
- # Remove the first Gap on the right in the list
- # in order to prevent global shifts when there is empty space
- while not done:
- i += 1
- if i >= len(self.tabs):
- done = True
- elif not self.tabs[i]:
- self.tabs.pop(i)
- done = True
- # Remove the trailing gaps
- i = len(self.tabs) - 1
- while isinstance(self.tabs[i], tabs.GapTab):
- self.tabs.pop()
- i -= 1
- return True
-
def insert_tab(self, old_pos, new_pos=99999):
"""
Insert a tab at a position, changing the number of the following tabs
returns False if it could not move the tab, True otherwise
"""
- if old_pos <= 0 or old_pos >= len(self.tabs):
- return False
- elif new_pos <= 0:
- return False
- elif new_pos == old_pos:
- return False
- elif not self.tabs[old_pos]:
- return False
- if config.get('create_gaps'):
- return self.insert_tab_gaps(old_pos, new_pos)
- return self.insert_tab_nogaps(old_pos, new_pos)
+ self.tabs.insert_tab(old_pos, new_pos, config.get('create_gaps'))
### Move actions (e.g. go to next room) ###
@@ -1122,22 +1027,18 @@ class Core:
"""
rotate the rooms list to the right
"""
- self.current_tab().on_lose_focus()
- self.current_tab_nb += 1
- while not self.tabs[self.current_tab_nb]:
- self.current_tab_nb += 1
- self.current_tab().on_gain_focus()
+ self.tabs.current_tab.on_lose_focus()
+ self.tabs.next()
+ self.tabs.current_tab.on_gain_focus()
self.refresh_window()
def rotate_rooms_left(self, args=None):
"""
rotate the rooms list to the right
"""
- self.current_tab().on_lose_focus()
- self.current_tab_nb -= 1
- while not self.tabs[self.current_tab_nb]:
- self.current_tab_nb -= 1
- self.current_tab().on_gain_focus()
+ self.tabs.current_tab.on_lose_focus()
+ self.tabs.prev()
+ self.tabs.current_tab.on_gain_focus()
self.refresh_window()
def go_to_room_number(self):
@@ -1183,7 +1084,7 @@ class Core:
priority = tabs.STATE_PRIORITY
tab_refs = {}
# put all the active tabs in a dict of lists by state
- for tab in self.tabs:
+ for tab in self.tabs.get_tabs():
if not tab:
continue
if tab.state not in tab_refs:
@@ -1197,8 +1098,8 @@ class Core:
for state in states:
for tab in tab_refs[state]:
- if (tab.nb < self.current_tab_nb
- and tab_refs[state][-1].nb > self.current_tab_nb):
+ if (tab.nb < self.tabs.current_tab_intex and
+ tab_refs[state][-1].nb > self.tabs.current_tab_index):
continue
self.command.win(str(tab.nb))
return
@@ -1206,33 +1107,14 @@ class Core:
def focus_tab_named(self, tab_name, type_=None):
"""Returns True if it found a tab to focus on"""
- for tab in self.tabs:
- if tab.name == tab_name:
- if (type_ and (isinstance(tab, type_))) or not type_:
- self.command.win(str(tab.nb))
- return True
- return False
-
- @property
- def current_tab_nb(self):
- """Wrapper for the current tab number"""
- return self._current_tab_nb
-
- @current_tab_nb.setter
- def current_tab_nb(self, value):
- """
- Prevents the tab number from going over the total number of opened
- tabs, or under 0
- """
- old = self._current_tab_nb
- if value >= len(self.tabs):
- self._current_tab_nb = 0
- elif value < 0:
- self._current_tab_nb = len(self.tabs) - 1
+ if type_ is None:
+ tab = self.tabs.by_name(tab_name)
else:
- self._current_tab_nb = value
- if old != self._current_tab_nb and self.tabs[self._current_tab_nb]:
- self.events.trigger('tab_change', old, self._current_tab_nb)
+ tab = self.tabs.by_name_and_class(tab_name, type_)
+ if tab:
+ self.command_win(str(tab.nb))
+ return True
+ return False
### Opening actions ###
@@ -1263,7 +1145,7 @@ class Core:
self.command.win(str(tab.nb))
return tab
# create the new tab
- tab = self.get_tab_by_name(room_name, tabs.MucTab)
+ tab = self.tabs.by_name_and_class(room_name, tabs.MucTab)
if not tab:
return None
new_tab = tabs.PrivateTab(self, complete_jid, tab.own_nick)
@@ -1303,8 +1185,8 @@ class Core:
this updates the name of all the opened private conversations
with him/her
"""
- tab = self.get_tab_by_name('%s/%s' % (room_name, old_nick),
- tabs.PrivateTab)
+ tab = self.tabs.by_name_and_class('%s/%s' % (room_name, old_nick),
+ tabs.PrivateTab)
if tab:
tab.rename_user(old_nick, user)
@@ -1314,8 +1196,8 @@ class Core:
The user left the MUC: add a message in the associated
private conversation
"""
- tab = self.get_tab_by_name('%s/%s' % (room_name, user.nick),
- tabs.PrivateTab)
+ tab = self.tabs.by_name_and_class('%s/%s' % (room_name, user.nick),
+ tabs.PrivateTab)
if tab:
tab.user_left(status_message, user)
@@ -1324,8 +1206,8 @@ class Core:
The user joined a MUC: add a message in the associated
private conversation
"""
- tab = self.get_tab_by_name('%s/%s' % (room_name, nick),
- tabs.PrivateTab)
+ tab = self.tabs.by_name_and_class('%s/%s' % (room_name, nick),
+ tabs.PrivateTab)
if tab:
tab.user_rejoined(nick)
@@ -1350,7 +1232,7 @@ class Core:
tab.activate(reason=reason)
def on_user_changed_status_in_private(self, jid, status):
- tab = self.get_tab_by_name(jid, tabs.ChatTab)
+ tab = self.tabs.by_name_and_class(jid, tabs.ChatTab)
if tab is not None: # display the message in private
tab.update_status(status)
@@ -1360,35 +1242,16 @@ class Core:
"""
was_current = tab is None
if tab is None:
- tab = self.current_tab()
+ tab = self.tabs.current_tab
if isinstance(tab, tabs.RosterInfoTab):
return # The tab 0 should NEVER be closed
tab.on_close()
del tab.key_func # Remove self references
del tab.commands # and make the object collectable
- nb = tab.nb
- if was_current:
- if self.previous_tab_nb != nb:
- self.current_tab_nb = self.previous_tab_nb
- self.previous_tab_nb = 0
- if config.get('create_gaps'):
- if nb >= len(self.tabs) - 1:
- self.tabs.remove(tab)
- nb -= 1
- while not self.tabs[nb]: # remove the trailing gaps
- self.tabs.pop()
- nb -= 1
- else:
- self.tabs[nb] = tabs.GapTab(self)
- else:
- self.tabs.remove(tab)
+ self.tabs.delete(tab, gap=config.get('create_gaps'))
logger.close(tab.name)
- if self.current_tab_nb >= len(self.tabs):
- self.current_tab_nb = len(self.tabs) - 1
- while not self.tabs[self.current_tab_nb]:
- self.current_tab_nb -= 1
if was_current:
- self.current_tab().on_gain_focus()
+ self.tabs.current_tab.on_gain_focus()
self.refresh_window()
import gc
gc.collect()
@@ -1401,10 +1264,10 @@ class Core:
Search for a ConversationTab with the given jid (full or bare),
if yes, add the given message to it
"""
- tab = self.get_tab_by_name(jid, tabs.ConversationTab)
+ tab = self.tabs.by_name_and_class(jid, tabs.ConversationTab)
if tab is not None:
tab.add_message(msg, typ=2)
- if self.current_tab() is tab:
+ if self.tabs.current_tab is tab:
self.refresh_window()
####################### Curses and ui-related stuff ###########################
@@ -1437,7 +1300,7 @@ class Core:
nb_lines = self.information_buffer.add_message(
msg, nickname=typ, nick_color=color)
popup_on = config.get('information_buffer_popup_on').split()
- if isinstance(self.current_tab(), tabs.RosterInfoTab):
+ if isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
self.refresh_window()
elif typ != '' and typ.lower() in popup_on:
popup_time = config.get('popup_time') + (nb_lines - 1) * 2
@@ -1445,7 +1308,7 @@ class Core:
else:
if self.information_win_size != 0:
self.information_win.refresh()
- self.current_tab().refresh_input()
+ self.tabs.current_tab.refresh_input()
return True
def _init_curses(self, stdscr):
@@ -1479,8 +1342,8 @@ class Core:
Refresh everything
"""
nocursor = curses.curs_set(0)
- self.current_tab().state = 'current'
- self.current_tab().refresh()
+ self.tabs.current_tab.state = 'current'
+ self.tabs.current_tab.refresh()
self.doupdate()
curses.curs_set(nocursor)
@@ -1488,7 +1351,7 @@ class Core:
"""
Refresh the window containing the tab list
"""
- self.current_tab().refresh_tab_win()
+ self.tabs.current_tab.refresh_tab_win()
self.refresh_input()
self.doupdate()
@@ -1496,8 +1359,8 @@ class Core:
"""
Refresh the input if it exists
"""
- if self.current_tab().input:
- self.current_tab().input.refresh()
+ if self.tabs.current_tab.input:
+ self.tabs.current_tab.input.refresh()
self.doupdate()
def scroll_page_down(self):
@@ -1505,7 +1368,7 @@ class Core:
Scroll a page down, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_scroll_down():
+ if self.tabs.current_tab.on_scroll_down():
self.refresh_window()
return True
@@ -1514,7 +1377,7 @@ class Core:
Scroll a page up, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_scroll_up():
+ if self.tabs.current_tab.on_scroll_up():
self.refresh_window()
return True
@@ -1523,7 +1386,7 @@ class Core:
Scroll a line up, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_line_up():
+ if self.tabs.current_tab.on_line_up():
self.refresh_window()
return True
@@ -1532,7 +1395,7 @@ class Core:
Scroll a line down, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_line_down():
+ if self.tabs.current_tab.on_line_down():
self.refresh_window()
return True
@@ -1541,7 +1404,7 @@ class Core:
Scroll half a screen down, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_half_scroll_up():
+ if self.tabs.current_tab.on_half_scroll_up():
self.refresh_window()
return True
@@ -1550,7 +1413,7 @@ class Core:
Scroll half a screen down, if possible.
Returns True on success, None on failure.
"""
- if self.current_tab().on_half_scroll_down():
+ if self.tabs.current_tab.on_half_scroll_down():
self.refresh_window()
return True
@@ -1558,8 +1421,8 @@ class Core:
"""
Expand the information win a number of lines
"""
- if self.information_win_size >= self.current_tab().height -5 or \
- self.information_win_size+nb >= self.current_tab().height-4 or\
+ if self.information_win_size >= self.tabs.current_tab.height -5 or \
+ self.information_win_size+nb >= self.tabs.current_tab.height-4 or\
self.size.core_degrade_y:
return 0
self.information_win_size += nb
@@ -1588,10 +1451,10 @@ class Core:
Scroll the information buffer up
"""
self.information_win.scroll_up(self.information_win.height)
- if not isinstance(self.current_tab(), tabs.RosterInfoTab):
+ if not isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
self.information_win.refresh()
else:
- info = self.current_tab().information_win
+ info = self.tabs.current_tab.information_win
info.scroll_up(info.height)
self.refresh_window()
@@ -1600,10 +1463,10 @@ class Core:
Scroll the information buffer down
"""
self.information_win.scroll_down(self.information_win.height)
- if not isinstance(self.current_tab(), tabs.RosterInfoTab):
+ if not isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
self.information_win.refresh()
else:
- info = self.current_tab().information_win
+ info = self.tabs.current_tab.information_win
info.scroll_down(info.height)
self.refresh_window()
@@ -1710,7 +1573,8 @@ class Core:
tab.need_resize = True
else:
tab.resize()
- if self.tabs:
+
+ if len(self.tabs):
self.full_screen_redraw()
def read_keyboard(self):
@@ -2050,7 +1914,7 @@ class Core:
for bm in bookmarks:
if not (bm.autojoin or config.get('open_all_bookmarks')):
continue
- tab = self.get_tab_by_name(bm.jid, tabs.MucTab)
+ tab = self.tabs.by_name_and_class(bm.jid, tabs.MucTab)
nick = bm.nick if bm.nick else self.own_nick
if not tab:
self.open_new_room(
@@ -2093,7 +1957,7 @@ class Core:
"""
Display the error in the tab
"""
- tab = self.get_tab_by_name(room_name, tabs.MucTab)
+ tab = self.tabs.by_name_and_class(room_name, tabs.MucTab)
if not tab:
return
error_message = self.get_error_message(error)