summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/default_config.cfg5
-rw-r--r--src/core.py76
-rw-r--r--src/tabs.py23
-rw-r--r--src/windows.py20
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
@@ -124,6 +121,15 @@ class Tab(object):
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:
Tab.tab_core = singleton.Singleton(core.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: