Mercurial > libervia-backend
diff frontends/src/primitivus/chat.py @ 1367:f71a0fc26886
merged branch frontends_multi_profiles
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 18 Mar 2015 10:52:28 +0100 |
parents | d3e9848b9574 |
children | 017270e6eea4 |
line wrap: on
line diff
--- a/frontends/src/primitivus/chat.py Thu Feb 05 11:59:26 2015 +0100 +++ b/frontends/src/primitivus/chat.py Wed Mar 18 10:52:28 2015 +0100 @@ -23,13 +23,15 @@ import urwid from urwid_satext import sat_widgets from urwid_satext.files_management import FileDialog +from sat_frontends.quick_frontend import quick_widgets from sat_frontends.quick_frontend.quick_chat import QuickChat -from sat_frontends.primitivus.card_game import CardGame -from sat_frontends.quick_frontend.quick_utils import escapePrivate, unescapePrivate +from sat_frontends.quick_frontend import quick_games +from sat_frontends.primitivus import game_tarot from sat_frontends.primitivus.constants import Const as C from sat_frontends.primitivus.keys import action_key_map as a_key +from sat_frontends.primitivus.widget import PrimitivusWidget import time -from sat_frontends.tools.jid import JID +from sat_frontends.tools import jid class ChatText(urwid.FlowWidget): @@ -80,19 +82,27 @@ return txt_widget -class Chat(urwid.WidgetWrap, QuickChat): +class Chat(PrimitivusWidget, QuickChat): - def __init__(self, target, host, type_='one2one'): - self.target = target - QuickChat.__init__(self, target, host, type_) + def __init__(self, host, target, type_=C.CHAT_ONE2ONE, profiles=None): + QuickChat.__init__(self, host, target, type_, profiles=profiles) self.content = urwid.SimpleListWalker([]) self.text_list = urwid.ListBox(self.content) self.chat_widget = urwid.Frame(self.text_list) self.chat_colums = urwid.Columns([('weight', 8, self.chat_widget)]) self.chat_colums = urwid.Columns([('weight', 8, self.chat_widget)]) self.pile = urwid.Pile([self.chat_colums]) - urwid.WidgetWrap.__init__(self, self.__getDecoration(self.pile)) - self.setType(type_) + PrimitivusWidget.__init__(self, self.pile, self.target) + + # we must adapt the behaviour with the type + if type_ == C.CHAT_ONE2ONE: + self.historyPrint(profile=self.profile) + elif type_ == C.CHAT_GROUP: + if len(self.chat_colums.contents) == 1: + present_widget = self._buildPresentList() + self.present_panel = sat_widgets.VerticalSeparator(present_widget) + self._appendPresentPanel() + self.day_change = time.strptime(time.strftime("%a %b %d 00:00:00 %Y")) #struct_time of day changing time self.show_timestamp = True self.show_short_nick = False @@ -101,12 +111,12 @@ def keypress(self, size, key): if key == a_key['OCCUPANTS_HIDE']: #user wants to (un)hide the presents panel - if self.type == 'group': + if self.type == C.CHAT_GROUP: widgets = [widget for (widget, options) in self.chat_colums.contents] if self.present_panel in widgets: - self.__removePresentPanel() + self._removePresentPanel() else: - self.__appendPresentPanel() + self._appendPresentPanel() elif key == a_key['TIMESTAMP_HIDE']: #user wants to (un)hide timestamp self.show_timestamp = not self.show_timestamp for wid in self.content: @@ -115,10 +125,6 @@ self.show_short_nick = not self.show_short_nick for wid in self.content: wid._invalidate() - elif key == a_key['DECORATION_HIDE']: #user wants to (un)hide widget decoration - show = not isinstance(self._w, sat_widgets.LabelLine) - self.showDecoration(show) - self._invalidate() elif key == a_key['SUBJECT_SWITCH']: #user wants to (un)hide group's subject or change its apperance if self.subject: self.show_title = (self.show_title + 1) % 3 @@ -130,67 +136,30 @@ self.chat_widget.header = None self._invalidate() - return super(Chat, self).keypress(size, key) def getMenu(self): """Return Menu bar""" menu = sat_widgets.Menu(self.host.loop) - if self.type == 'group': + if self.type == C.CHAT_GROUP: self.host.addMenus(menu, C.MENU_ROOM, {'room_jid': self.target.bare}) game = _("Game") menu.addMenu(game, "Tarot", self.onTarotRequest) - elif self.type == 'one2one': - self.host.addMenus(menu, C.MENU_SINGLE, {'jid': unescapePrivate(self.target)}) + elif self.type == C.CHAT_ONE2ONE: + self.host.addMenus(menu, C.MENU_SINGLE, {'jid': self.target}) menu.addMenu(_("Action"), _("Send file"), self.onSendFileRequest) return menu - def setType(self, type_): - QuickChat.setType(self, type_) - if type_ == 'one2one': - self.historyPrint(profile=self.host.profile) - elif type_ == 'group': - if len(self.chat_colums.contents) == 1: - present_widget = self.__buildPresentList() - self.present_panel = sat_widgets.VerticalSeparator(present_widget) - self.__appendPresentPanel() - - def __getDecoration(self, widget): - return sat_widgets.LabelLine(widget, self.__getSurrendedText()) - - def __getSurrendedText(self): - """Get the text to be displayed as the dialog title.""" - if not hasattr(self, "surrended_text"): - self.__setSurrendedText() - return self.surrended_text - - def __setSurrendedText(self, state=None): - """Set the text to be displayed as the dialog title - @param stat: chat state of the contact - """ - text = unicode(unescapePrivate(self.target)) - if state: - text += " (" + state + ")" - self.surrended_text = sat_widgets.SurroundedText(text) - - def showDecoration(self, show=True): - """Show/Hide the decoration around the chat window""" - if show: - main_widget = self.__getDecoration(self.pile) - else: - main_widget = self.pile - self._w = main_widget - - def updateChatState(self, state, nick=None): - """Set the chat state (XEP-0085) of the contact. Leave nick to None - to set the state for a one2one conversation, or give a nickname or - C.ALL_OCCUPANTS to set the state of a participant within a MUC. - @param state: the new chat state - @param nick: None for one2one, the MUC user nick or C.ALL_OCCUPANTS - """ - if nick: - assert(self.type == 'group') - occupants = self.occupants if nick == C.ALL_OCCUPANTS else [nick] + def updateChatState(self, from_jid, state): + if self.type == C.CHAT_GROUP: + if from_jid == C.ENTITY_ALL: + occupants = self.occupants + else: + nick = from_jid.resource + if not nick: + log.debug("no nick found for chatstate") + return + occupants = [nick] options = self.present_wid.getAllValues() for index in xrange(0, len(options)): nick = options[index].value @@ -199,46 +168,51 @@ self.present_wid.changeValues(options) self.host.redraw() else: - assert(self.type == 'one2one') - self.__setSurrendedText(state) - self.showDecoration() - self.host.redraw() + self.title_dynamic = '({})'.format(state) def _presentClicked(self, list_wid, clicked_wid): - assert(self.type == 'group') + assert self.type == C.CHAT_GROUP nick = clicked_wid.getValue().value if nick == self.getUserNick(): - #We ignore click on our own nick + #We ignore clicks on our own nick return - #we have a click on a nick, we add the private conversation to the contact_list - full_jid = JID("%s/%s" % (self.target.bare, nick)) - new_jid = escapePrivate(full_jid) - if new_jid not in self.host.contact_list: - self.host.contact_list.add(new_jid, [C.GROUP_NOT_IN_ROSTER]) + contact_list = self.host.contact_lists[self.profile] + full_jid = jid.JID("%s/%s" % (self.target.bare, nick)) + + #we have a click on a nick, we need to create the widget if it doesn't exists + self.getOrCreatePrivateWidget(full_jid) #now we select the new window - self.host.contact_list.setFocus(full_jid, True) + contact_list.setFocus(full_jid, True) - def __buildPresentList(self): + def _buildPresentList(self): self.present_wid = sat_widgets.GenericList([],option_type = sat_widgets.ClickableText, on_click=self._presentClicked) return self.present_wid - def __appendPresentPanel(self): + def _appendPresentPanel(self): self.chat_colums.contents.append((self.present_panel,('weight', 2, False))) - def __removePresentPanel(self): + def _removePresentPanel(self): for widget, options in self.chat_colums.contents: if widget is self.present_panel: self.chat_colums.contents.remove((widget, options)) break - def __appendGamePanel(self, widget): + def addGamePanel(self, widget): + """Insert a game panel to this Chat dialog. + + @param widget (Widget): the game panel + """ assert (len(self.pile.contents) == 1) - self.pile.contents.insert(0,(widget,('weight', 1))) - self.pile.contents.insert(1,(urwid.Filler(urwid.Divider('-'),('fixed', 1)))) + self.pile.contents.insert(0, (widget, ('weight', 1))) + self.pile.contents.insert(1, (urwid.Filler(urwid.Divider('-'), ('fixed', 1)))) self.host.redraw() - def __removeGamePanel(self): + def removeGamePanel(self, widget): + """Remove the game panel from this Chat dialog. + + @param widget (Widget): the game panel + """ assert (len(self.pile.contents) == 3) del self.pile.contents[0] self.host.redraw() @@ -252,12 +226,11 @@ self.chat_widget.header = urwid.AttrMap(self.subj_wid,'title') self.host.redraw() - def setPresents(self, param_nicks): - """Set the users presents in the contact list for a group chat - @param nicks: list of nicknames + def setPresents(self, nicks): + """Set the occupants of a group chat. + + @param nicks (list[unicode]): sorted list of nicknames """ - nicks = [unicode(nick) for nick in param_nicks] #FIXME: should be done in DBus bridge - nicks.sort() QuickChat.setPresents(self, nicks) self.present_wid.changeValues(nicks) self.host.redraw() @@ -290,13 +263,22 @@ self.text_list.focus_position = len(self.content) - 1 # scroll down self.host.redraw() - def printMessage(self, from_jid, msg, profile, timestamp=None): - assert isinstance(from_jid, JID) + def onPrivateCreated(self, widget): + self.host.contact_lists[widget.profile].specialResourceVisible(widget.target) + + def printMessage(self, from_jid, msg, extra=None, profile=C.PROF_KEY_NONE): + assert isinstance(from_jid, jid.JID) + if extra is None: + extra = {} try: - jid, nick, mymess = QuickChat.printMessage(self, from_jid, msg, profile, timestamp) + timestamp = float(extra['timestamp']) + except KeyError: + timestamp=None + try: + nick, mymess = QuickChat.printMessage(self, from_jid, msg, extra, profile) except TypeError: + # None is returned, the message is managed return - new_text = ChatText(self, timestamp, nick, mymess, msg) if timestamp and self.content: @@ -323,7 +305,7 @@ # all messages and not only with the messages coming from the history. self._notify(from_jid, msg) - def printInfo(self, msg, type_='normal', timestamp=None): + def printInfo(self, msg, type_='normal', extra=None): """Print general info @param msg: message to print @type_: one of: @@ -331,6 +313,12 @@ me: "/me" information like "/me clenches his fist" ==> "toto clenches his fist" @param timestamp (float): number of seconds since epoch """ + if extra is None: + extra = {} + try: + timestamp = float(extra['timestamp']) + except KeyError: + timestamp=None _widget = ChatText(self, timestamp, None, False, msg, is_info=True) self.content.append(_widget) self._notify(msg=msg) @@ -348,30 +336,18 @@ self.text_list.focus_position = len(self.content) - 1 self.host.redraw() if not self.host.x_notify.hasFocus(): - if self.type == "one2one": + if self.type == C.CHAT_ONE2ONE: self.host.x_notify.sendNotification(_("Primitivus: %s is talking to you") % from_jid) elif self.getUserNick().lower() in msg.lower(): self.host.x_notify.sendNotification(_("Primitivus: %(user)s mentioned you in room '%(room)s'") % {'user': from_jid, 'room': self.target}) - def startGame(self, game_type, referee, players): - """Configure the chat window to start a game""" - if game_type=="Tarot": - self.tarot_wid = CardGame(self, referee, players, self.nick) - self.__appendGamePanel(self.tarot_wid) - - def getGame(self, game_type): - """Return class managing the game type""" - #TODO: check that the game is launched, and manage errors - if game_type=="Tarot": - return self.tarot_wid - #MENU EVENTS# def onTarotRequest(self, menu): # TODO: move this to plugin_misc_tarot with dynamic menu if len(self.occupants) != 4: self.host.showPopUp(sat_widgets.Alert(_("Can't start game"), _("You need to be exactly 4 peoples in the room to start a Tarot game"), ok_cb=self.host.removePopUp)) else: - self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.host.profile) + self.host.bridge.tarotGameCreate(self.id, list(self.occupants), self.profile) def onSendFileRequest(self, menu): # TODO: move this to core with dynamic menus @@ -388,11 +364,15 @@ self.host.showDialog(_(u"File has a unicode error in its name, it's not yet managed by SàT"), title=_("Can't send file"), type_="error") return #FIXME: check last_resource: what if self.target.resource exists ? - last_resource = self.host.bridge.getLastResource(unicode(self.target.bare), self.host.profile) + last_resource = self.host.bridge.getMainResource(unicode(self.target.bare), self.profile) if last_resource: - full_jid = JID("%s/%s" % (self.target.bare, last_resource)) + full_jid = jid.JID("%s/%s" % (self.target.bare, last_resource)) else: full_jid = self.target - progress_id = self.host.bridge.sendFile(full_jid, filepath, {}, self.host.profile) + progress_id = self.host.bridge.sendFile(full_jid, filepath, {}, self.profile) self.host.addProgress(progress_id,filepath) self.host.showDialog(_(u"You file request has been sent, we are waiting for your contact answer"), title=_("File request sent")) + + +quick_widgets.register(QuickChat, Chat) +quick_widgets.register(quick_games.Tarot, game_tarot.TarotGame)