From fb40ac54fc6e9fe79f29fd99e836187e95bb0509 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 5 Mar 2011 21:42:56 +0100 Subject: Kind of big cleanup. Core and Connection classes are now used as singletons, we do not need to pass them to each Tab and Win. This remove a lot of arguments to varius methods. --- src/connection.py | 6 +- src/core.py | 54 ++++++++------- src/data_forms.py | 14 ++-- src/poezio.py | 17 +++-- src/singleton.py | 29 ++++++++ src/tabs.py | 193 ++++++++++++++++++++++++++++-------------------------- src/windows.py | 71 +++++++------------- 7 files changed, 194 insertions(+), 190 deletions(-) create mode 100644 src/singleton.py (limited to 'src') 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 +# +# 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 . + +""" +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() -- cgit v1.2.3