From 09ff076bc44eed93a570af29e04bdd720ce9569a Mon Sep 17 00:00:00 2001 From: mathieui Date: Wed, 26 Sep 2012 01:54:20 +0200 Subject: Rewrite the tab number handling - Now the tab number is computed instead of assigned and fixed - Added tabs.GapTab to keep the old behaviour - Added a create_gaps option, defaults to true (may change in the future) - If there are gaps before using /set to change the option to false, they will be removed. (this is a preparation for the move_tab command) --- data/default_config.cfg | 5 ++++ src/core.py | 76 +++++++++++++++++++++++++++++++------------------ src/tabs.py | 23 +++++++++++++-- src/windows.py | 20 ++++++------- 4 files changed, 82 insertions(+), 42 deletions(-) diff --git a/data/default_config.cfg b/data/default_config.cfg index 8c09d90f..a2c62206 100644 --- a/data/default_config.cfg +++ b/data/default_config.cfg @@ -280,6 +280,11 @@ themes_dir = # theme will be used instead theme = +# Whether to create gaps when moving or closing a tab +# (a gap means that the number of your tabs does not depend of the previous tabs +# but only of the creation order) +create_gaps = true + # If true, a vertical list of tabs, with their name, is displayed on the left of # the screen. enable_vertical_tab_list = false diff --git a/src/core.py b/src/core.py index c8ce2324..1c3faa36 100644 --- a/src/core.py +++ b/src/core.py @@ -131,6 +131,7 @@ class Core(object): self.xml_buffer = TextBuffer() self.tabs = [] + self._current_tab_nb = 0 self.previous_tab_nb = 0 self.own_nick = config.get('default_nick', '') or self.xmpp.boundjid.user @@ -617,7 +618,8 @@ class Core(object): """ returns the current room, the one we are viewing """ - return self.tabs[0] + self.current_tab_nb = self.current_tab_nb + return self.tabs[self.current_tab_nb] def get_conversation_by_jid(self, jid, create=True): """ @@ -652,9 +654,8 @@ class Core(object): return None def get_tab_by_number(self, number): - for tab in self.tabs: - if tab.nb == number: - return tab + if 0 <= number < len(self.tabs): + return self.tabs[number] return None def add_tab(self, new_tab, focus=False): @@ -662,13 +663,7 @@ class Core(object): Appends the new_tab in the tab list and focus it if focus==True """ - if self.current_tab().nb == 0: - self.tabs.append(new_tab) - else: - for ta in self.tabs: - if ta.nb == 0: - self.tabs.insert(self.tabs.index(ta), new_tab) - break + self.tabs.append(new_tab) if focus: self.command_win("%s" % new_tab.nb) @@ -679,7 +674,9 @@ class Core(object): rotate the rooms list to the right """ self.current_tab().on_lose_focus() - self.tabs.append(self.tabs.pop(0)) + 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.refresh_window() @@ -688,7 +685,9 @@ class Core(object): rotate the rooms list to the right """ self.current_tab().on_lose_focus() - self.tabs.insert(0, self.tabs.pop()) + 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.refresh_window() @@ -733,6 +732,19 @@ class Core(object): if tab.get_name() == tab_name: self.command_win('%s' % (tab.nb,)) + @property + def current_tab_nb(self): + return self._current_tab_nb + + @current_tab_nb.setter + def current_tab_nb(self, value): + if value >= len(self.tabs): + self._current_tab_nb = 0 + elif value < 0: + self._current_tab_nb = len(self.tabs) - 1 + else: + self._current_tab_nb = value + ### Opening actions ### def open_conversation_window(self, jid, focus=True): @@ -852,12 +864,22 @@ class Core(object): del tab.key_func # Remove self references del tab.commands # and make the object collectable tab.on_close() - self.tabs.remove(tab) - if tab.get_name() in logger.fds: + nb = tab.nb + if config.get('create_gaps', 'false').lower() == 'true': + if nb >= len(self.tabs) - 1: + self.tabs.remove(tab) + else: + self.tabs[nb] = tabs.GapTab() + else: + self.tabs.remove(tab) + if tab and tab.get_name() in logger.fds: logger.fds[tab.get_name()].close() log.debug("Log file for %s closed.", tab.get_name()) del logger.fds[tab.get_name()] - self.tabs[0].on_gain_focus() + 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 self.refresh_window() import gc gc.collect() @@ -1332,22 +1354,17 @@ class Core(object): nb = int(arg.split()[0]) except ValueError: nb = arg - if self.current_tab().nb == nb: + if self.current_tab_nb == nb: return - self.previous_tab_nb = self.current_tab().nb + self.previous_tab_nb = self.current_tab_nb self.current_tab().on_lose_focus() - start = self.current_tab() - self.tabs.append(self.tabs.pop(0)) if isinstance(nb, int): - while self.current_tab().nb != nb: - self.tabs.append(self.tabs.pop(0)) - if self.current_tab() == start: - break + if 0 <= nb < len(self.tabs): + self.current_tab_nb = nb else: - while nb not in safeJID(self.current_tab().get_name()).user: - self.tabs.append(self.tabs.pop(0)) - if self.current_tab() is start: - break + for tab in self.tabs: + if nb in safeJID(tab.get_name()).user: + self.current_tab_nb = tab.nb self.current_tab().on_gain_focus() self.refresh_window() @@ -1790,6 +1807,9 @@ class Core(object): value = args[2] config.set_and_save(option, value, section) msg = "%s=%s" % (option, value) + # Remove all gaptabs if switching from gaps to nogaps + if option == 'create_gaps' and value.lower() == 'false': + self.tabs = list(filter(lambda x: bool(x), self.tabs)) self.information(msg, 'Info') def completion_set(self, the_input): diff --git a/src/tabs.py b/src/tabs.py index 60f98abc..327ecfba 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -99,7 +99,6 @@ STATE_PRIORITY = { } class Tab(object): - number = 0 tab_core = None def __init__(self): self.input = None @@ -109,8 +108,6 @@ class Tab(object): self._state = 'normal' self.need_resize = False - self.nb = Tab.number - Tab.number += 1 self.need_resize = False self.key_func = {} # each tab should add their keys in there # and use them in on_input @@ -123,6 +120,15 @@ class Tab(object): Tab.tab_core = singleton.Singleton(core.Core) return Tab.tab_core + @property + def nb(self): + log.debug("COUCOU TABS") + for index, tab in enumerate(self.core.tabs): + log.debug("%s", tab.__class__) + if tab == self: + return index + return len(self.core.tabs) + @property def tab_win(self): if not Tab.tab_core: @@ -363,6 +369,17 @@ class Tab(object): def __del__(self): log.debug('------ Closing tab %s', self.__class__.__name__) +class GapTab(Tab): + + def __bool__(self): + return False + + def __len__(self): + return 0 + + def get_name(self): + return '' + class ChatTab(Tab): """ A tab containing a chat of any type. diff --git a/src/windows.py b/src/windows.py index 6e1fd9ec..a8af3b7f 100644 --- a/src/windows.py +++ b/src/windows.py @@ -316,24 +316,25 @@ class GlobalInfoBar(Win): def refresh(self): log.debug('Refresh: %s',self.__class__.__name__) - def compare_room(a): - return a.nb - comp = lambda x: x.nb with g_lock: self._win.erase() self.addstr(0, 0, "[", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) - sorted_tabs = sorted(self.core.tabs, key=comp) + + create_gaps = config.getl('create_gaps', 'false') == 'true' show_names = config.getl('show_tab_names', 'false') == 'true' show_nums = config.getl('show_tab_numbers', 'true') != 'false' use_nicks = config.getl('use_tab_nicks', 'true') != 'false' - for tab in sorted_tabs: + # ignore any remaining gap tabs if the feature is not enabled + sorted_tabs = [tab for tab in self.core.tabs if tab] if not create_gaps else self.core.tabs[:] + for nb, tab in enumerate(sorted_tabs): + if not tab: continue color = tab.color if config.get('show_inactive_tabs', 'true') == 'false' and\ color is get_theme().COLOR_TAB_NORMAL: continue try: if show_nums or not show_names: - self.addstr("%s" % str(tab.nb), to_curses_attr(color)) + self.addstr("%s" % str(nb), to_curses_attr(color)) if show_names: self.addstr(' ', to_curses_attr(color)) if show_names: @@ -358,16 +359,13 @@ class VerticalGlobalInfoBar(Win): self._win = scr def refresh(self): - def compare_room(a): - return a.nb - comp = lambda x: x.nb with g_lock: height, width = self._win.getmaxyx() self._win.erase() - sorted_tabs = sorted(self.core.tabs, key=comp) + sorted_tabs = [tab for tab in self.core.tabs if tab] if config.get('show_inactive_tabs', 'true') == 'false': sorted_tabs = [tab for tab in sorted_tabs if\ - tab.vertical_color is not get_theme().COLOR_VERTICAL_TAB_NORMAL] + tab.vertical_color != get_theme().COLOR_VERTICAL_TAB_NORMAL] nb_tabs = len(sorted_tabs) use_nicks = config.getl('use_tab_nicks', 'true') != 'false' if nb_tabs >= height: -- cgit v1.2.3