summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connection.py6
-rw-r--r--src/core.py54
-rw-r--r--src/data_forms.py14
-rw-r--r--src/poezio.py17
-rw-r--r--src/singleton.py29
-rw-r--r--src/tabs.py193
-rw-r--r--src/windows.py71
7 files changed, 194 insertions, 190 deletions
diff --git a/src/connection.py b/src/connection.py
index c12680b8..089c43b8 100644
--- a/src/connection.py
+++ b/src/connection.py
@@ -37,10 +37,11 @@ class Connection(sleekxmpp.ClientXMPP):
Receives everything from Jabber and emits the
appropriate signals
"""
+ __init = False
def __init__(self):
resource = config.get('resource', '')
if config.get('jid', ''):
- self.anon = False # Field used to know if we are anonymous or not.
+ self.anon = False # Field used to know if we are anonymous or not.
# many features will be handled diferently
# depending on this setting
jid = '%s/%s' % (config.get('jid', ''), resource)
@@ -79,6 +80,3 @@ class Connection(sleekxmpp.ClientXMPP):
return False
self.process(threaded=True)
return True
-
-# Global connection object
-connection = Connection()
diff --git a/src/core.py b/src/core.py
index d3dce5be..457cc90e 100644
--- a/src/core.py
+++ b/src/core.py
@@ -16,7 +16,6 @@
from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
-from os.path import isfile
from time import sleep
@@ -32,6 +31,7 @@ from datetime import datetime
import common
import theme
import logging
+import singleton
from sleekxmpp.xmlstream.stanzabase import JID
@@ -40,9 +40,9 @@ log = logging.getLogger(__name__)
import multiuserchat as muc
import tabs
import windows
+import connection
from data_forms import DataFormsTab
-from connection import connection
from config import config
from logger import logger
from user import User
@@ -87,23 +87,18 @@ class Core(object):
"""
User interface using ncurses
"""
- def __init__(self, xmpp):
+ def __init__(self):
# All uncaught exception are given to this callback, instead
# of being displayed on the screen and exiting the program.
sys.excepthook = self.on_exception
self.running = True
- self.stdscr = curses.initscr()
- self.init_curses(self.stdscr)
- self.xmpp = xmpp
+ self.xmpp = singleton.Singleton(connection.Connection)
# a unique buffer used to store global informations
# that are displayed in almost all tabs, in an
# information window.
self.information_buffer = TextBuffer()
self.information_win_size = config.get('info_win_height', 2, 'var')
- default_tab = tabs.InfoTab(self) if self.xmpp.anon\
- else tabs.RosterInfoTab(self)
- default_tab.on_gain_focus()
- self.tabs = [default_tab]
+ self.tabs = []
self.previous_tab_nb = 0
self.own_nick = config.get('own_nick', '') or self.xmpp.boundjid.user
# global commands, available from all tabs
@@ -175,6 +170,17 @@ class Core(object):
self.xmpp.add_event_handler("chatstate_paused", self.on_chatstate_paused)
self.xmpp.add_event_handler("chatstate_gone", self.on_chatstate_gone)
self.xmpp.add_event_handler("chatstate_inactive", self.on_chatstate_inactive)
+
+ def start(self):
+ """
+ Init curses, create the first tab, etc
+ """
+ self.stdscr = curses.initscr()
+ self.init_curses(self.stdscr)
+ default_tab = tabs.InfoTab() if self.xmpp.anon\
+ else tabs.RosterInfoTab()
+ default_tab.on_gain_focus()
+ self.tabs.append(default_tab)
self.information(_('Welcome to poezio!'))
self.refresh_window()
@@ -189,9 +195,11 @@ class Core(object):
pass
sys.__excepthook__(typ, value, trace)
+ @property
+ def informations(self):
+ return self.information_buffer
+
def grow_information_win(self):
- """
- """
if self.information_win_size == 14:
return
self.information_win_size += 1
@@ -200,8 +208,6 @@ class Core(object):
self.refresh_window()
def shrink_information_win(self):
- """
- """
if self.information_win_size == 0:
return
self.information_win_size -= 1
@@ -273,7 +279,7 @@ class Core(object):
The callback are called with the completed form as parameter in
addition with kwargs
"""
- form_tab = DataFormsTab(self, form, on_cancel, on_send, kwargs)
+ form_tab = DataFormsTab(form, on_cancel, on_send, kwargs)
self.add_tab(form_tab, True)
def on_got_offline(self, presence):
@@ -380,11 +386,6 @@ class Core(object):
if not tab:
self.open_new_room(jid.bare, nick, False)
muc.join_groupchat(self.xmpp, jid.bare, nick)
- # if not self.xmpp.anon:
- # Todo: SEND VCARD
- return
- if config.get('jid', '') == '': # Don't send the vcard if we're not anonymous
- self.vcard_sender.start() # because the user ALREADY has one on the server
def on_groupchat_presence(self, presence):
"""
@@ -835,7 +836,7 @@ class Core(object):
Refresh everything
"""
self.current_tab().set_color_state(theme.COLOR_TAB_CURRENT)
- self.current_tab().refresh(self.tabs, self.information_buffer, roster)
+ self.current_tab().refresh()
self.doupdate()
def add_tab(self, new_tab, focus=False):
@@ -858,7 +859,7 @@ class Core(object):
Open a new tab.MucTab containing a muc Room, using the specified nick
"""
r = Room(room, nick)
- new_tab = tabs.MucTab(self, r)
+ new_tab = tabs.MucTab(r)
self.add_tab(new_tab, focus)
self.refresh_window()
@@ -952,7 +953,7 @@ class Core(object):
"""
open a new conversation tab and focus it if needed
"""
- new_tab = tabs.ConversationTab(self, jid)
+ new_tab = tabs.ConversationTab(jid)
# insert it in the rooms
self.add_tab(new_tab, focus)
self.refresh_window()
@@ -971,7 +972,7 @@ class Core(object):
return None
own_nick = room.own_nick
r = Room(complete_jid, own_nick) # PrivateRoom here
- new_tab = tabs.PrivateTab(self, r)
+ new_tab = tabs.PrivateTab(r)
# insert it in the tabs
self.add_tab(new_tab, focus)
# self.window.new_room(r)
@@ -1123,7 +1124,7 @@ class Core(object):
server = JID(self.current_tab().get_name()).server
else:
server = arg.strip()
- list_tab = tabs.MucListTab(self, server)
+ list_tab = tabs.MucListTab(server)
self.add_tab(list_tab, True)
self.xmpp.plugin['xep_0030'].get_items(jid=server, block=False, callback=list_tab.on_muc_list_item_received)
@@ -1473,6 +1474,3 @@ class Core(object):
return
self.current_tab().just_before_refresh()
curses.doupdate()
-
-# global core object
-core = Core(connection)
diff --git a/src/data_forms.py b/src/data_forms.py
index 3b756304..f9e4dcff 100644
--- a/src/data_forms.py
+++ b/src/data_forms.py
@@ -31,8 +31,8 @@ class DataFormsTab(Tab):
A tab contaning various window type, displaying
a form that the user needs to fill.
"""
- def __init__(self, core, form, on_cancel, on_send, kwargs):
- Tab.__init__(self, core)
+ def __init__(self, form, on_cancel, on_send, kwargs):
+ Tab.__init__(self)
self._form = form
self._on_cancel = on_cancel
self._on_send = on_send
@@ -74,11 +74,11 @@ class DataFormsTab(Tab):
Tab.resize(self)
if not self.visible:
return
- self.topic_win.resize(1, self.width, 0, 0, self.core.stdscr)
- self.tab_win.resize(1, self.width, self.height-2, 0, self.core.stdscr)
+ self.topic_win.resize(1, self.width, 0, 0)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
self.form_win.resize(self.height-4, self.width, 1, 0)
- self.help_win.resize(1, self.width, self.height-1, 0, None)
- self.help_win_dyn.resize(1, self.width, self.height-3, 0, None)
+ self.help_win.resize(1, self.width, self.height-1, 0)
+ self.help_win_dyn.resize(1, self.width, self.height-3, 0)
self.lines = []
def refresh(self, tabs, informations, _):
@@ -108,7 +108,7 @@ class FieldInput(object):
raise NotImplementedError
def resize(self, height, width, y, x):
- self._resize(height, width, y, x, None)
+ self._resize(height, width, y, x)
def is_dummy(self):
return False
diff --git a/src/poezio.py b/src/poezio.py
index cbe30f2a..bc93ec62 100644
--- a/src/poezio.py
+++ b/src/poezio.py
@@ -26,18 +26,17 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
import signal
import logging
-from connection import connection
from config import config, options
-from core import core
+import singleton
+import core
+import connection
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_IGN) # ignore ctrl-c
- sys.stderr = open('/dev/null', 'a')
if options.debug:
logging.basicConfig(filename=options.debug,level=logging.DEBUG)
- if not connection.start(): # Connect to remote server
- core.on_failed_connection()
- # Disable any display of non-wanted text on the terminal
- # by redirecting stderr to /dev/null
- # sys.stderr = open('/dev/null', 'a')
- core.main_loop() # Refresh the screen, wait for user events etc
+ the_core = singleton.Singleton(core.Core)
+ the_core.start()
+ if not the_core.xmpp.start(): # Connect to remote server
+ the_core.on_failed_connection()
+ the_core.main_loop() # Refresh the screen, wait for user events etc
diff --git a/src/singleton.py b/src/singleton.py
new file mode 100644
index 00000000..c47fb269
--- /dev/null
+++ b/src/singleton.py
@@ -0,0 +1,29 @@
+# Copyright 2010-2011 Le Coz Florent <louiz@louiz.org>
+#
+# This file is part of Poezio.
+#
+# Poezio is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# Poezio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Defines a Singleton function that initialize an object
+of the given class if it was never instantiated yet. Else, returns
+the previously instantiated object.
+This method is the only one that I can come up with that do not call
+__init__() each time.
+"""
+
+instances = {}
+def Singleton(cls, *args, **kwargs):
+ if not cls in instances:
+ instances[cls] = cls(*args, **kwargs)
+ return instances[cls]
diff --git a/src/tabs.py b/src/tabs.py
index ad43672a..f35efb7a 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -19,7 +19,7 @@ a Tab object is a way to organize various Windows (see windows.py)
around the screen at once.
A tab is then composed of multiple Buffer.
Each Tab object has different refresh() and resize() methods, defining how its
-Buffer are displayed, resized, etc
+Windows are displayed, resized, etc
"""
MIN_WIDTH = 50
@@ -38,6 +38,8 @@ import difflib
import text_buffer
import string
import common
+import core
+import singleton
from sleekxmpp.xmlstream.stanzabase import JID
from config import config
@@ -48,9 +50,8 @@ import multiuserchat as muc
class Tab(object):
number = 0
-
- def __init__(self, core):
- self.core = core # a pointer to core, to access its attributes (ugly?)
+ tab_core = None
+ def __init__(self):
self._color_state = theme.COLOR_TAB_NORMAL
self.need_resize = False
self.nb = Tab.number
@@ -64,6 +65,12 @@ class Tab(object):
# and use them in on_input
self.commands = {} # and their own commands
+ @property
+ def core(self):
+ if not Tab.tab_core:
+ Tab.tab_core = singleton.Singleton(core.Core)
+ return Tab.tab_core
+
def complete_commands(self, the_input):
"""
Does command completion on the specified input for both global and tab-specific
@@ -126,7 +133,7 @@ class Tab(object):
self.visible = True
self.need_resize = False
- def refresh(self, tabs, informations, roster):
+ def refresh(self):
"""
Called on each screen refresh (when something has changed)
"""
@@ -222,8 +229,8 @@ class ChatTab(Tab):
Also, ^M is already bound to on_enter
And also, add the /say command
"""
- def __init__(self, core, room):
- Tab.__init__(self, core)
+ def __init__(self, room):
+ Tab.__init__(self)
self._room = room
self.remote_wants_chatstates = None # change this to True or False when
# we know that the remote user wants chatstates, or not.
@@ -286,10 +293,10 @@ class ChatTab(Tab):
class TabWithInfoWin(Tab):
def __init__(self):
self.info_win = windows.TextWin(20)
- self.core.information_buffer.add_window(self.info_win)
+ self.core.informations.add_window(self.info_win)
def __del__(self):
- self.core.information_buffer.del_window(self.info_win)
+ self.core.informations.del_window(self.info_win)
del self.info_win
Tab.__del__(self)
@@ -298,8 +305,8 @@ class InfoTab(ChatTab, TabWithInfoWin):
The information tab, used to display global informations
when using a anonymous account
"""
- def __init__(self, core):
- Tab.__init__(self, core)
+ def __init__(self):
+ Tab.__init__(self)
TabWithInfoWin.__init__(self)
self.tab_win = windows.GlobalInfoBar()
self.input = windows.Input()
@@ -314,17 +321,17 @@ class InfoTab(ChatTab, TabWithInfoWin):
Tab.resize(self)
if not self.visible:
return
- self.tab_win.resize(1, self.width, self.height-2, 0, self.core.stdscr)
- self.info_win.resize(self.height-2, self.width, 0, 0, self.core.stdscr)
- self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.info_win.resize(self.height-2, self.width, 0, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
- def refresh(self, tabs, informations, _):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
self.resize()
- self.info_win.refresh(informations)
- self.tab_win.refresh(tabs, tabs[0])
+ self.info_win.refresh(self.core.informations)
+ self.tab_win.refresh()
self.input.refresh()
def completion(self):
@@ -377,8 +384,8 @@ class MucTab(ChatTab, TabWithInfoWin):
It contains an userlist, an input, a topic, an information and a chat zone
"""
message_type = 'groupchat'
- def __init__(self, core, room):
- ChatTab.__init__(self, core, room)
+ def __init__(self, room):
+ ChatTab.__init__(self, room)
TabWithInfoWin.__init__(self)
self.remote_wants_chatstates = True
# We send active, composing and paused states to the MUC because
@@ -611,17 +618,17 @@ class MucTab(ChatTab, TabWithInfoWin):
if self.core.information_win_size >= self.height-3:
return
text_width = (self.width//10)*9
- self.topic_win.resize(1, self.width, 0, 0, self.core.stdscr)
- self.text_win.resize(self.height-4-self.core.information_win_size, text_width, 1, 0, self.core.stdscr)
+ self.topic_win.resize(1, self.width, 0, 0)
+ self.text_win.resize(self.height-4-self.core.information_win_size, text_width, 1, 0)
self.text_win.rebuild_everything(self._room)
- self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10), self.core.stdscr)
- self.user_win.resize(self.height-3, self.width-text_width-1, 1, text_width+1, self.core.stdscr)
- self.info_header.resize(1, (self.width//10)*9, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, (self.width//10)*9, self.height-2-self.core.information_win_size, 0, self.core.stdscr, self.core.information_buffer)
- 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 refresh(self, tabs, informations, _):
+ self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10))
+ self.user_win.resize(self.height-3, self.width-text_width-1, 1, text_width+1)
+ self.info_header.resize(1, (self.width//10)*9, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, (self.width//10)*9, self.height-2-self.core.information_win_size, 0, self.core.informations)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
+
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
@@ -631,8 +638,8 @@ class MucTab(ChatTab, TabWithInfoWin):
self.v_separator.refresh()
self.user_win.refresh(self._room.users)
self.info_header.refresh(self._room, self.text_win)
- self.tab_win.refresh(tabs, tabs[0])
- self.info_win.refresh(informations)
+ self.tab_win.refresh()
+ self.info_win.refresh(self.core.informations)
self.input.refresh()
def on_input(self, key):
@@ -703,9 +710,9 @@ class MucTab(ChatTab, TabWithInfoWin):
if self.core.information_win_size >= self.height-3:
return
text_width = (self.width//10)*9
- self.text_win.resize(self.height-4-self.core.information_win_size, text_width, 1, 0, self.core.stdscr)
- self.info_header.resize(1, (self.width//10)*9, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, (self.width//10)*9, self.height-2-self.core.information_win_size, 0, self.core.stdscr)
+ self.text_win.resize(self.height-4-self.core.information_win_size, text_width, 1, 0)
+ self.info_header.resize(1, (self.width//10)*9, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, (self.width//10)*9, self.height-2-self.core.information_win_size, 0)
def just_before_refresh(self):
return
@@ -718,8 +725,8 @@ class PrivateTab(ChatTab, TabWithInfoWin):
The tab containg a private conversation (someone from a MUC)
"""
message_type = 'chat'
- def __init__(self, core, room):
- ChatTab.__init__(self, core, room)
+ def __init__(self, room):
+ ChatTab.__init__(self, room)
TabWithInfoWin.__init__(self)
self.text_win = windows.TextWin()
room.add_window(self.text_win)
@@ -759,22 +766,22 @@ class PrivateTab(ChatTab, TabWithInfoWin):
return
if self.core.information_win_size >= self.height-3:
return
- self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0, self.core.stdscr)
+ self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
self.text_win.rebuild_everything(self._room)
- self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.stdscr, self.core.information_buffer)
- 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)
+ self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.information_buffer)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
- def refresh(self, tabs, informations, _):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
self.resize()
self.text_win.refresh(self._room)
self.info_header.refresh(self._room, self.text_win, self.chatstate)
- self.info_win.refresh(informations)
- self.tab_win.refresh(tabs, tabs[0])
+ self.info_win.refresh(self.core.informations)
+ self.tab_win.refresh()
self.input.refresh()
def get_color_state(self):
@@ -821,9 +828,9 @@ class PrivateTab(ChatTab, TabWithInfoWin):
def on_info_win_size_changed(self):
if self.core.information_win_size >= self.height-3:
return
- self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0, self.core.stdscr)
- self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.stdscr, None)
+ self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
+ self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, None)
def get_room(self):
return self._room
@@ -841,8 +848,8 @@ class RosterInfoTab(Tab):
"""
A tab, splitted in two, containing the roster and infos
"""
- def __init__(self, core):
- Tab.__init__(self, core)
+ def __init__(self):
+ Tab.__init__(self)
self.name = "Roster"
self.v_separator = windows.VerticalSeparator()
self.tab_win = windows.GlobalInfoBar()
@@ -879,12 +886,12 @@ class RosterInfoTab(Tab):
return
roster_width = self.width//2
info_width = self.width-roster_width-1
- self.v_separator.resize(self.height-2, 1, 0, roster_width, self.core.stdscr)
- self.tab_win.resize(1, self.width, self.height-2, 0, self.core.stdscr)
- self.info_win.resize(self.height-2-4, info_width, 0, roster_width+1, self.core.stdscr, self.core.information_buffer)
- self.roster_win.resize(self.height-2, roster_width, 0, 0, self.core.stdscr)
- self.contact_info_win.resize(4, info_width, self.height-2-4, roster_width+1, self.core.stdscr)
- self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
+ self.v_separator.resize(self.height-2, 1, 0, roster_width)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.info_win.resize(self.height-2-4, info_width, 0, roster_width+1, self.core.information_buffer)
+ self.roster_win.resize(self.height-2, roster_width, 0, 0)
+ self.contact_info_win.resize(4, info_width, self.height-2-4, roster_width+1)
+ self.input.resize(1, self.width, self.height-1, 0)
def completion(self):
# Check if we are entering a command (with the '/' key)
@@ -971,7 +978,7 @@ class RosterInfoTab(Tab):
self.core.xmpp.sendPresence(pto=jid, ptype='subscribed')
self.core.xmpp.sendPresence(pto=jid, ptype='subscribe')
- def refresh(self, tabs, informations, roster):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
@@ -980,8 +987,8 @@ class RosterInfoTab(Tab):
self.roster_win.refresh(roster)
self.contact_info_win.refresh(self.roster_win.get_selected_row())
# self.core.global_information_win.refresh(informations)
- self.info_win.refresh(informations)
- self.tab_win.refresh(tabs, tabs[0])
+ self.info_win.refresh(self.core.informations)
+ self.tab_win.refresh()
self.input.refresh()
def get_name(self):
@@ -1017,7 +1024,7 @@ class RosterInfoTab(Tab):
"""
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.resize(1, self.width, self.height-1, 0)
self.input.do_command("/") # we add the slash
def reset_help_message(self, _=None):
@@ -1098,13 +1105,13 @@ class RosterInfoTab(Tab):
"""
curses.curs_set(1)
self.input = windows.CommandInput("[Search]", self.on_search_terminate, self.on_search_terminate, self.set_roster_filter)
- self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
+ self.input.resize(1, self.width, self.height-1, 0)
return True
def start_search_slow(self):
curses.curs_set(1)
self.input = windows.CommandInput("[Search]", self.on_search_terminate, self.on_search_terminate, self.set_roster_filter_slow)
- self.input.resize(1, self.width, self.height-1, 0, self.core.stdscr)
+ self.input.resize(1, self.width, self.height-1, 0)
return True
def set_roster_filter_slow(self, txt):
@@ -1134,9 +1141,9 @@ class ConversationTab(ChatTab, TabWithInfoWin):
The tab containg a normal conversation (not from a MUC)
"""
message_type = 'chat'
- def __init__(self, core, jid):
+ def __init__(self, jid):
txt_buff = text_buffer.TextBuffer()
- ChatTab.__init__(self, core, txt_buff)
+ ChatTab.__init__(self, txt_buff)
TabWithInfoWin.__init__(self)
self.color_state = theme.COLOR_TAB_NORMAL
self._name = jid # a conversation tab is linked to one specific full jid OR bare jid
@@ -1176,15 +1183,15 @@ class ConversationTab(ChatTab, TabWithInfoWin):
return
if self.core.information_win_size >= self.height-3:
return
- self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0, self.core.stdscr)
+ self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
self.text_win.rebuild_everything(self._room)
- self.upper_bar.resize(1, self.width, 0, 0, self.core.stdscr)
- self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.stdscr, self.core.information_buffer)
- 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)
+ self.upper_bar.resize(1, self.width, 0, 0)
+ self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.information_buffer)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
- def refresh(self, tabs, informations, roster):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
@@ -1192,8 +1199,8 @@ class ConversationTab(ChatTab, TabWithInfoWin):
self.text_win.refresh(self._room)
self.upper_bar.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()))
self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._room, self.text_win, self.chatstate)
- self.info_win.refresh(informations)
- self.tab_win.refresh(tabs, tabs[0])
+ self.info_win.refresh(self.core.informations)
+ self.tab_win.refresh()
self.input.refresh()
def get_color_state(self):
@@ -1240,9 +1247,9 @@ class ConversationTab(ChatTab, TabWithInfoWin):
def on_info_win_size_changed(self):
if self.core.information_win_size >= self.height-3:
return
- self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0, self.core.stdscr)
- self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0, self.core.stdscr)
- self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, self.core.stdscr)
+ self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
+ self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
+ self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0)
def get_room(self):
return self._room
@@ -1262,8 +1269,8 @@ 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)
+ def __init__(self, server):
+ Tab.__init__(self)
self._color_state = theme.COLOR_TAB_NORMAL
self.name = server
self.upper_message = windows.Topic()
@@ -1285,7 +1292,7 @@ class MucListTab(Tab):
self.commands['close'] = (self.close, _("Usage: /close\nClose: Just close this tab"), None)
self.resize()
- def refresh(self, tabs, informations, roster):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
@@ -1293,23 +1300,23 @@ class MucListTab(Tab):
self.upper_message.refresh()
self.list_header.refresh()
self.listview.refresh()
- self.tab_win.refresh(tabs, tabs[0])
+ self.tab_win.refresh()
self.input.refresh()
def resize(self):
Tab.resize(self)
if not self.visible:
return
- self.upper_message.resize(1, self.width, 0, 0, self.core.stdscr)
+ self.upper_message.resize(1, self.width, 0, 0)
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.list_header.resize(1, self.width, 1, 0)
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)
+ self.listview.resize(self.height-4, self.width, 2, 0)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
def on_slash(self):
"""
@@ -1317,7 +1324,7 @@ class MucListTab(Tab):
"""
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.resize(1, self.width, self.height-1, 0)
self.input.do_command("/") # we add the slash
def close(self, arg=None):
@@ -1396,8 +1403,8 @@ class SimpleTextTab(Tab):
information or whatever.
For example used to display tracebacks
"""
- def __init__(self, core, text):
- Tab.__init__(self, core)
+ def __init__(self, text):
+ Tab.__init__(self)
self._color_state = theme.COLOR_TAB_NORMAL
self.text_win = windows.SimpleTextWin(text)
self.tab_win = windows.GlobalInfoBar()
@@ -1413,7 +1420,7 @@ class SimpleTextTab(Tab):
"""
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.resize(1, self.width, self.height-1, 0)
self.input.do_command("/") # we add the slash
def on_input(self, key):
@@ -1430,17 +1437,17 @@ class SimpleTextTab(Tab):
Tab.resize(self)
if not self.visible:
return
- self.text_win.resize(self.height-2, self.width, 0, 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)
+ self.text_win.resize(self.height-2, self.width, 0, 0)
+ self.tab_win.resize(1, self.width, self.height-2, 0)
+ self.input.resize(1, self.width, self.height-1, 0)
- def refresh(self, tabs, information, roster):
+ def refresh(self):
if not self.visible:
return
if self.need_resize:
self.resize()
self.text_win.refresh()
- self.tab_win.refresh(tabs, tabs[0])
+ self.tab_win.refresh()
self.input.refresh()
def on_lose_focus(self):
diff --git a/src/windows.py b/src/windows.py
index 01566506..2dcef920 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -46,24 +46,33 @@ from tabs import MIN_WIDTH, MIN_HEIGHT
from sleekxmpp.xmlstream.stanzabase import JID
+import core
import theme
import common
import wcwidth
+import singleton
g_lock = Lock()
LINES_NB_LIMIT = 4096
class Win(object):
+ _win_core = None
def __init__(self):
pass
- def _resize(self, height, width, y, x, parent_win):
+ def _resize(self, height, width, y, x):
self.height, self.width, self.x, self.y = height, width, x, y
if height == 0 or width == 0:
return
self._win = curses.newwin(height, width, y, x)
+ def resize(self, height, width, y, x):
+ """
+ Override if something has to be done on resize
+ """
+ self._resize(height, width, y, x)
+
def _refresh(self):
self._win.noutrefresh()
@@ -93,6 +102,12 @@ class Win(object):
size = self.width-x
self.addnstr(' '*size, size, common.curses_color_pair(color))
+ @property
+ def core(self):
+ if not Win._win_core:
+ Win._win_core = singleton.Singleton(core.Core)
+ return Win._win_core
+
class UserList(Win):
def __init__(self):
Win.__init__(self)
@@ -154,8 +169,8 @@ class UserList(Win):
self.draw_plus(self.height-1)
self._refresh()
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
+ def resize(self, height, width, y, x):
+ self._resize(height, width, y, x)
self._win.attron(common.curses_color_pair(theme.COLOR_VERTICAL_SEPARATOR))
self._win.vline(0, 0, curses.ACS_VLINE, self.height)
self._win.attroff(common.curses_color_pair(theme.COLOR_VERTICAL_SEPARATOR))
@@ -165,9 +180,6 @@ class Topic(Win):
Win.__init__(self)
self._message = ''
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, topic=None):
with g_lock:
self._win.erase()
@@ -190,18 +202,14 @@ class GlobalInfoBar(Win):
def __init__(self):
Win.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
- def refresh(self, tabs, current):
+ def refresh(self):
def compare_room(a):
- # return a.nb - b.nb
return a.nb
comp = lambda x: x.nb
with g_lock:
self._win.erase()
self.addstr(0, 0, "[", common.curses_color_pair(theme.COLOR_INFORMATION_BAR))
- sorted_tabs = sorted(tabs, key=comp)
+ sorted_tabs = sorted(self.core.tabs, key=comp)
for tab in sorted_tabs:
color = tab.get_color_state()
if config.get('show_inactive_tabs', 'true') == 'false' and\
@@ -246,9 +254,6 @@ class PrivateInfoWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, room, window, chatstate):
with g_lock:
@@ -288,9 +293,6 @@ class ConversationInfoWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, jid, contact, text_buffer, window, chatstate):
# contact can be None, if we receive a message
# from someone not in our roster. In this case, we display
@@ -360,9 +362,6 @@ class ConversationStatusMessageWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, jid, contact):
jid = JID(jid)
if contact:
@@ -390,9 +389,6 @@ class MucInfoWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, room, window=None):
with g_lock:
self._win.erase()
@@ -660,8 +656,8 @@ class TextWin(Win):
self.addstr(theme.CHAR_TIME_RIGHT, common.curses_color_pair(theme.COLOR_TIME_LIMITER))
self.addstr(' ')
- def resize(self, height, width, y, x, stdscr, room=None):
- self._resize(height, width, y, x, stdscr)
+ def resize(self, height, width, y, x, room=None):
+ self._resize(height, width, y, x)
if room:
self.rebuild_everything(room)
@@ -684,9 +680,6 @@ class HelpText(Win):
Win.__init__(self)
self.txt = text
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self, txt=None):
if txt:
self.txt = txt
@@ -751,11 +744,6 @@ class Input(Win):
def is_empty(self):
return len(self.text) == 0
- def resize(self, height, width, y, x, stdscr=None): # TODO remove stdscr
- self._resize(height, width, y, x, stdscr)
- # self._win.erase()
- # self.addnstr(0, 0, self.text, self.width-1)
-
def jump_word_left(self):
"""
Move the cursor one word to the left
@@ -1199,9 +1187,6 @@ class VerticalSeparator(Win):
self._win.vline(0, 0, curses.ACS_VLINE, self.height, common.curses_color_pair(theme.COLOR_VERTICAL_SEPARATOR))
self._refresh()
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def refresh(self):
self.rewrite_line()
@@ -1223,9 +1208,6 @@ class RosterWin(Win):
self.roster_len = 0
self.selected_row = None
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def move_cursor_down(self):
"""
Return True if we scrolled, False otherwise
@@ -1408,9 +1390,6 @@ class ContactInfoWin(Win):
def __init__(self):
Win.__init__(self)
- def resize(self, height, width, y, x, stdscr):
- self._resize(height, width, y, x, stdscr)
-
def draw_contact_info(self, contact):
"""
draw the contact information
@@ -1464,9 +1443,6 @@ class ListWin(Win):
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
@@ -1556,9 +1532,6 @@ class ColumnHeaderWin(Win):
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()