Commit fb40ac54 authored by louiz’'s avatar louiz’

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.
parent 9c291d13
......@@ -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()
......@@ -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)
......@@ -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
......
......@@ -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
# 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]
This diff is collapsed.
......@@ -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()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment