gui.py 7.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#!/usr/bin/python
# -*- coding:utf-8 -*-
#
# Copyright 2010 Le Coz Florent <louizatakk@fedoraproject.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/>.

from handler import Handler
import curses
from curses import textpad

24
import locale
25 26
from datetime import datetime

27 28 29
locale.setlocale(locale.LC_ALL, '')
code = locale.getpreferredencoding()

30 31
import sys

32
from connection import *
33
from window import Window
34

35
class User(object):
36
    """
37
    keep trace of an user in a Room
38
    """
39 40 41
    def __init__(self, nick, affiliation, show, status, role):
        self.update(affiliation, show, status, role)
        self.change_nick(nick)
42

43 44 45 46 47
    def update(self, affiliation, show, status, role):
        self.affiliation = None
        self.show = None
        self.status = status
        self.role = role
48

49
    def change_nick(self, nick):
50
        self.nick = nick.encode('utf-8')
51

52
class Room(object):
53 54
    """
    """
55
    def __init__(self, name, nick):
56
        self.name = name
57 58 59 60 61
        self.own_nick = nick
        self.joined = False     # false until self presence is received
        self.users = []
        self.lines = []         # (time, nick, msg) or (time, info)
        self.topic = ''
62

63
    def add_message(self, nick, msg):
64
        self.lines.append((datetime.now(), nick.encode('utf-8'), msg.encode('utf-8')))
65

66 67 68
    def add_info(self, info):
        """ info, like join/quit/status messages"""
        self.lines.append((datetime.now(), info.encode('utf-8')))
69

70
    def on_presence(self, stanza, nick):
71 72
        """
        """
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
        affiliation = stanza.getAffiliation()
        show = stanza.getShow()
        status = stanza.getStatus()
        role = stanza.getRole()
        if not self.joined:
             self.users.append(User(nick, affiliation, show, status, role))
             if nick == self.own_nick:
                 self.joined = True
             self.add_info("%s is in the room" % (nick))
             return
        change_nick = stanza.getStatusCode() == '303'
        for user in self.users:
            if user.nick == nick:
                if change_nick:
                    user.change_nick(stanza.getNick())
                    self.add_info('%s is now known as %s' % (nick, stanza.getNick()))
                    return
                if status == 'offline':
                    self.users.remove(user)
                    self.add_info('%s has left the room' % (nick))
                    return
                user.update(affiliation, show, status, role)
                self.add_info('%s, status : %s, %s, %s, %s' % (nick, affiliation, role, show, status))
                return
        self.users.append(User(nick, affiliation, show, status, role))
        self.add_info('%s joined the room %s' % (nick, self.name))
99

100 101 102 103
class Gui(object):
    """
    Graphical user interface using ncurses
    """
104 105 106 107 108 109 110 111 112 113
    def __init__(self, stdscr=None, muc=None):

        self.init_curses(stdscr)
        self.stdscr = stdscr
        self.stdscr.leaveok(True)
        self.rooms = [Room('Info', '')]         # current_room is self.rooms[0]
        self.window = Window(stdscr)
        self.window.refresh(self.rooms[0])

        self.muc = muc
114

115 116 117
        self.commands = {
            'join': self.command_join,
            'quit': self.command_quit,
118 119
            'next': self.rotate_rooms_left,
            'prev': self.rotate_rooms_right,
120 121
            }

122

123 124 125 126 127 128 129 130 131 132 133
        self.handler = Handler()
        self.handler.connect('on-connected', self.on_connected)
        self.handler.connect('join-room', self.join_room)
        self.handler.connect('room-presence', self.room_presence)
        self.handler.connect('room-message', self.room_message)

    def init_curses(self, stdscr):
        curses.start_color()
        curses.noecho()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK)
134 135 136
        curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK) # Admin
        curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLACK) # Participant
        curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_BLACK) # Visitor
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

    def on_connected(self):
        pass

    def join_room(self, room, nick):
        self.rooms.insert(0, Room(room, nick))
        self.window.refresh(self.rooms[0])

    def rotate_rooms_left(self, args):
        self.rooms.append(self.rooms.pop(0))
        self.window.refresh(self.rooms[0])

    def rotate_rooms_right(self, args):
        self.rooms.insert(0, self.rooms.pop())
        self.window.refresh(self.rooms[0])

    def room_message(self, stanza):
        if stanza.getType() != 'groupchat':
            return  # ignore all messages not comming from a MUC
        room_from = stanza.getFrom().getStripped()
        nick_from = stanza.getFrom().getResource()
        for room in self.rooms:
            if room_from == room.name:
                room.add_message(nick_from, stanza.getBody())
                if room == self.rooms[0]:
162 163 164 165 166
                    self.window.text_win.refresh(room.lines)
                    self.window.user_win.refresh(room.users)
                    self.window.input.refresh()
#                    self.window.refresh(self.rooms[0])
                    curses.doupdate()
167 168 169 170 171 172 173 174 175 176 177
                break

    def room_presence(self, stanza):
        from_nick = stanza.getFrom().getResource()
        from_room = stanza.getFrom().getStripped()
        for room in self.rooms:
            if from_room == room.name:
                room.on_presence(stanza, from_nick)
                if room == self.rooms[0]:
                    self.window.text_win.refresh(room.lines)
                    self.window.user_win.refresh(room.users)
178
                    curses.doupdate()
179
                break
180 181

    def execute(self):
182 183 184 185
        line = self.window.input.get_text()
        self.window.input.clear_text()
        if line == "":
            return
186 187 188 189 190 191 192
        if line.strip().startswith('/'):
            command = line.strip()[:].split()[0][1:]
            args = line.strip()[:].split()[1:]
            if command in self.commands.keys():
                func = self.commands[command]
                func(args)
            return
193 194
        if self.rooms[0].name != 'Info':
            self.muc.send_message(self.rooms[0].name, line)
195 196 197

    def command_join(self, args):
        room = args[0]
198 199
        self.muc.join_room(room, "poezio")
        self.join_room(room, 'poezio')
200 201 202

    def command_quit(self, args):
        sys.exit()
203

204 205
    def main_loop(self, stdscr):
        while 1:
206
            curses.doupdate()
207
            # self.window.input.refresh()
208 209
            key = stdscr.getch()
            if key == curses.KEY_RESIZE:
210
                self.window.resize(stdscr)
211
            elif key == 10:
212 213
                self.execute()
            else:
214
                self.window.do_command(key)