# HG changeset patch # User souliane # Date 1378660382 -7200 # Node ID 3b02554d4c8be53dcc569b4ae49b653339fcfcf5 # Parent 7ea6d5a86e580d188395d24aa40ff31294408f7c primitivus: chat state implementation for now chat states are displayed in primitivus surrended text (after the contact's name) diff -r 7ea6d5a86e58 -r 3b02554d4c8b frontends/src/primitivus/chat.py --- a/frontends/src/primitivus/chat.py Thu Sep 05 20:48:47 2013 +0200 +++ b/frontends/src/primitivus/chat.py Sun Sep 08 19:13:02 2013 +0200 @@ -145,7 +145,22 @@ self.__appendPresentPanel() def __getDecoration(self, widget): - return sat_widgets.LabelLine(widget, sat_widgets.SurroundedText(unicode(unescapePrivate(self.target)))) + 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""" @@ -155,6 +170,18 @@ main_widget = self.pile self._w = main_widget + def updateChatState(self, state): + """Update the chat state of the contact. + @param state: new state to set + """ + if (self.type == 'one2one'): + self.__setSurrendedText(state) + self.showDecoration() + self.host.redraw() + elif (self.type == 'group'): + # TODO: chat state for groupchat + pass + def _presentClicked(self, list_wid, clicked_wid): assert(self.type == 'group') nick = clicked_wid.getValue() diff -r 7ea6d5a86e58 -r 3b02554d4c8b frontends/src/primitivus/primitivus --- a/frontends/src/primitivus/primitivus Thu Sep 05 20:48:47 2013 +0200 +++ b/frontends/src/primitivus/primitivus Sun Sep 08 19:13:02 2013 +0200 @@ -49,6 +49,85 @@ def createChat(self, target): return Chat(target, self.host) + +class EditBar(sat_widgets.ModalEdit): + """ + The modal edit bar where you would enter messages and commands. + """ + + def __init__(self, app): + modes = {None: ('NORMAL', u''), + 'i': ('INSERTION', u'> '), + ':': ('COMMAND', u':')} #XXX: captions *MUST* be unicode + super(EditBar, self).__init__(modes) + self.app = app + self.setCompletionMethod(self._text_completion) + urwid.connect_signal(self, 'click', self.onTextEntered) + + def _text_completion(self, text, completion_data, mode): + if mode == 'INSERTION': + return self._nick_completion(text, completion_data) + else: + return text + + def _nick_completion(self, text, completion_data): + """Completion method which complete pseudo in group chat + for params, see AdvancedEdit""" + contact = self.app.contact_list.getContact() ###Based on the fact that there is currently only one contact selectable at once + if contact: + chat = self.app.chat_wins[contact] + if chat.type != "group": + return text + space = text.rfind(" ") + start = text[space+1:] + nicks = list(chat.occupants) + nicks.sort() + try: + start_idx=nicks.index(completion_data['last_nick'])+1 + if start_idx == len(nicks): + start_idx = 0 + except (KeyError,ValueError): + start_idx = 0 + for idx in range(start_idx,len(nicks)) + range(0,start_idx): + if nicks[idx].lower().startswith(start.lower()): + completion_data['last_nick'] = nicks[idx] + return text[:space+1] + nicks[idx] + (': ' if space < 0 else '') + return text + + def onTextEntered(self, editBar): + """Called when text is entered in the main edit bar""" + if self.mode == 'INSERTION': + contact = self.app.contact_list.getContact() ###Based on the fact that there is currently only one contact selectableat once + if contact: + chat = self.app.chat_wins[contact] + try: + self.app.sendMessage(contact, + editBar.get_edit_text(), + mess_type = "groupchat" if chat.type == 'group' else "chat", + profile_key=self.app.profile) + except: + self.app.notify(_("Error while sending message")) + editBar.set_edit_text('') + elif self.mode == 'COMMAND': + self.commandHandler() + + def commandHandler(self): + #TODO: separate class with auto documentation (with introspection) + # and completion method + command = self.get_edit_text() + if command == 'quit': + self.app.onExit() + raise urwid.ExitMainLoop() + + def keypress(self, size, key): + """Callback when a key is pressed. Send "composing" states.""" + if key != "enter": + contact = self.app.contact_list.getContact() + if contact: + self.app.bridge.chatStateComposing(contact, self.app.profile) + return super(EditBar, self).keypress(size, key) + + class PrimitivusApp(QuickApp): def __init__(self): @@ -172,13 +251,6 @@ except AttributeError: return input - def commandHandler(self, editBar): - #TODO: separate class with auto documentation (with introspection) - # and completion method - command = editBar.get_edit_text() - if command == 'quit': - self.onExit() - raise urwid.ExitMainLoop() def __buildMenuRoller(self): menu = sat_widgets.Menu(self.loop) @@ -215,48 +287,11 @@ #self.center_part = urwid.Columns([('weight',2,self.contact_list),('weight',8,Chat('',self))]) self.center_part = urwid.Columns([('weight',2,self.contact_list), ('weight',8,urwid.Filler(urwid.Text('')))]) - modes = {None: ('NORMAL', u''), - 'i': ('INSERTION', u'> '), - ':': ('COMMAND', u':')} #XXX: captions *MUST* be unicode - self.editBar = sat_widgets.ModalEdit(modes) - self.editBar.setCompletionMethod(self._text_completion) - urwid.connect_signal(self.editBar,'click',self.onTextEntered) + self.editBar = EditBar(self) self.menu_roller = self.__buildMenuRoller() self.main_widget = sat_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer') return self.main_widget - def _text_completion(self, text, completion_data, mode): - if mode == 'INSERTION': - return self._nick_completion(text, completion_data) - else: - return text - - def _nick_completion(self, text, completion_data): - """Completion method which complete pseudo in group chat - for params, see AdvancedEdit""" - contact = self.contact_list.getContact() ###Based on the fact that there is currently only one contact selectable at once - if contact: - chat = self.chat_wins[contact] - if chat.type != "group": - return text - space = text.rfind(" ") - start = text[space+1:] - nicks = list(chat.occupants) - nicks.sort() - try: - start_idx=nicks.index(completion_data['last_nick'])+1 - if start_idx == len(nicks): - start_idx = 0 - except (KeyError,ValueError): - start_idx = 0 - for idx in range(start_idx,len(nicks)) + range(0,start_idx): - if nicks[idx].lower().startswith(start.lower()): - completion_data['last_nick'] = nicks[idx] - return text[:space+1] + nicks[idx] + (': ' if space < 0 else '') - return text - - - def plug_profile(self, profile_key='@DEFAULT@'): self.loop.widget = self.__buildMainWidget() self.redraw() @@ -320,23 +355,6 @@ self.center_part.widget_list[1] = self.chat_wins[contact] self.menu_roller.addMenu(_('Chat menu'), self.chat_wins[contact].getMenu()) - def onTextEntered(self, editBar): - """Called when text is entered in the main edit bar""" - if self.mode == 'INSERTION': - contact = self.contact_list.getContact() ###Based on the fact that there is currently only one contact selectableat once - if contact: - chat = self.chat_wins[contact] - try: - self.sendMessage(contact, - editBar.get_edit_text(), - mess_type = "groupchat" if chat.type == 'group' else "chat", - profile_key=self.profile) - except: - self.notify(_("Error while sending message")) - editBar.set_edit_text('') - elif self.mode == 'COMMAND': - self.commandHandler(editBar) - def newMessage(self, from_jid, to_jid, msg, _type, extra, profile): QuickApp.newMessage(self, from_jid, to_jid, msg, _type, extra, profile) @@ -576,6 +594,24 @@ self.showPopUp(sat_widgets.Alert(_("Error"), _("Can't get search UI"), ok_cb=self.removePopUp)) self.bridge.searchRequest(search_jid, dict(data), self.profile, callback=success, errback=failure) + def chatStateReceived(self, from_jid_s, state, profile): + """Signal observer to display a contact chat state + @param from_jid_s: contact who sent his new state + @state: state + @profile: current profile + """ + if not self.check_profile(profile): + return + + if from_jid_s == "@ALL@": + for win in self.chat_wins: + self.chat_wins[win].updateChatState(state) + return + + from_bare = JID(from_jid_s).short + if from_bare in self.chat_wins: + self.chat_wins[from_bare].updateChatState(state) + sat = PrimitivusApp() sat.start()