comparison frontends/src/primitivus/primitivus @ 637:3b02554d4c8b

primitivus: chat state implementation for now chat states are displayed in primitivus surrended text (after the contact's name)
author souliane <souliane@mailoo.org>
date Sun, 08 Sep 2013 19:13:02 +0200
parents ca2cae6b2c6d
children 6821fc06a324
comparison
equal deleted inserted replaced
636:7ea6d5a86e58 637:3b02554d4c8b
46 class ChatList(QuickChatList): 46 class ChatList(QuickChatList):
47 """This class manage the list of chat windows""" 47 """This class manage the list of chat windows"""
48 48
49 def createChat(self, target): 49 def createChat(self, target):
50 return Chat(target, self.host) 50 return Chat(target, self.host)
51
52
53 class EditBar(sat_widgets.ModalEdit):
54 """
55 The modal edit bar where you would enter messages and commands.
56 """
57
58 def __init__(self, app):
59 modes = {None: ('NORMAL', u''),
60 'i': ('INSERTION', u'> '),
61 ':': ('COMMAND', u':')} #XXX: captions *MUST* be unicode
62 super(EditBar, self).__init__(modes)
63 self.app = app
64 self.setCompletionMethod(self._text_completion)
65 urwid.connect_signal(self, 'click', self.onTextEntered)
66
67 def _text_completion(self, text, completion_data, mode):
68 if mode == 'INSERTION':
69 return self._nick_completion(text, completion_data)
70 else:
71 return text
72
73 def _nick_completion(self, text, completion_data):
74 """Completion method which complete pseudo in group chat
75 for params, see AdvancedEdit"""
76 contact = self.app.contact_list.getContact() ###Based on the fact that there is currently only one contact selectable at once
77 if contact:
78 chat = self.app.chat_wins[contact]
79 if chat.type != "group":
80 return text
81 space = text.rfind(" ")
82 start = text[space+1:]
83 nicks = list(chat.occupants)
84 nicks.sort()
85 try:
86 start_idx=nicks.index(completion_data['last_nick'])+1
87 if start_idx == len(nicks):
88 start_idx = 0
89 except (KeyError,ValueError):
90 start_idx = 0
91 for idx in range(start_idx,len(nicks)) + range(0,start_idx):
92 if nicks[idx].lower().startswith(start.lower()):
93 completion_data['last_nick'] = nicks[idx]
94 return text[:space+1] + nicks[idx] + (': ' if space < 0 else '')
95 return text
96
97 def onTextEntered(self, editBar):
98 """Called when text is entered in the main edit bar"""
99 if self.mode == 'INSERTION':
100 contact = self.app.contact_list.getContact() ###Based on the fact that there is currently only one contact selectableat once
101 if contact:
102 chat = self.app.chat_wins[contact]
103 try:
104 self.app.sendMessage(contact,
105 editBar.get_edit_text(),
106 mess_type = "groupchat" if chat.type == 'group' else "chat",
107 profile_key=self.app.profile)
108 except:
109 self.app.notify(_("Error while sending message"))
110 editBar.set_edit_text('')
111 elif self.mode == 'COMMAND':
112 self.commandHandler()
113
114 def commandHandler(self):
115 #TODO: separate class with auto documentation (with introspection)
116 # and completion method
117 command = self.get_edit_text()
118 if command == 'quit':
119 self.app.onExit()
120 raise urwid.ExitMainLoop()
121
122 def keypress(self, size, key):
123 """Callback when a key is pressed. Send "composing" states."""
124 if key != "enter":
125 contact = self.app.contact_list.getContact()
126 if contact:
127 self.app.bridge.chatStateComposing(contact, self.app.profile)
128 return super(EditBar, self).keypress(size, key)
129
51 130
52 class PrimitivusApp(QuickApp): 131 class PrimitivusApp(QuickApp):
53 132
54 def __init__(self): 133 def __init__(self):
55 QuickApp.__init__(self) 134 QuickApp.__init__(self)
170 try: 249 try:
171 return self.menu_roller.checkShortcuts(input) 250 return self.menu_roller.checkShortcuts(input)
172 except AttributeError: 251 except AttributeError:
173 return input 252 return input
174 253
175 def commandHandler(self, editBar):
176 #TODO: separate class with auto documentation (with introspection)
177 # and completion method
178 command = editBar.get_edit_text()
179 if command == 'quit':
180 self.onExit()
181 raise urwid.ExitMainLoop()
182 254
183 def __buildMenuRoller(self): 255 def __buildMenuRoller(self):
184 menu = sat_widgets.Menu(self.loop) 256 menu = sat_widgets.Menu(self.loop)
185 general = _("General") 257 general = _("General")
186 menu.addMenu(general, _("Connect"), self.onConnectRequest) 258 menu.addMenu(general, _("Connect"), self.onConnectRequest)
213 def __buildMainWidget(self): 285 def __buildMainWidget(self):
214 self.contact_list = ContactList(self, on_click = self.contactSelected, on_change=lambda w: self.redraw()) 286 self.contact_list = ContactList(self, on_click = self.contactSelected, on_change=lambda w: self.redraw())
215 #self.center_part = urwid.Columns([('weight',2,self.contact_list),('weight',8,Chat('',self))]) 287 #self.center_part = urwid.Columns([('weight',2,self.contact_list),('weight',8,Chat('',self))])
216 self.center_part = urwid.Columns([('weight',2,self.contact_list), ('weight',8,urwid.Filler(urwid.Text('')))]) 288 self.center_part = urwid.Columns([('weight',2,self.contact_list), ('weight',8,urwid.Filler(urwid.Text('')))])
217 289
218 modes = {None: ('NORMAL', u''), 290 self.editBar = EditBar(self)
219 'i': ('INSERTION', u'> '),
220 ':': ('COMMAND', u':')} #XXX: captions *MUST* be unicode
221 self.editBar = sat_widgets.ModalEdit(modes)
222 self.editBar.setCompletionMethod(self._text_completion)
223 urwid.connect_signal(self.editBar,'click',self.onTextEntered)
224 self.menu_roller = self.__buildMenuRoller() 291 self.menu_roller = self.__buildMenuRoller()
225 self.main_widget = sat_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer') 292 self.main_widget = sat_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer')
226 return self.main_widget 293 return self.main_widget
227
228 def _text_completion(self, text, completion_data, mode):
229 if mode == 'INSERTION':
230 return self._nick_completion(text, completion_data)
231 else:
232 return text
233
234 def _nick_completion(self, text, completion_data):
235 """Completion method which complete pseudo in group chat
236 for params, see AdvancedEdit"""
237 contact = self.contact_list.getContact() ###Based on the fact that there is currently only one contact selectable at once
238 if contact:
239 chat = self.chat_wins[contact]
240 if chat.type != "group":
241 return text
242 space = text.rfind(" ")
243 start = text[space+1:]
244 nicks = list(chat.occupants)
245 nicks.sort()
246 try:
247 start_idx=nicks.index(completion_data['last_nick'])+1
248 if start_idx == len(nicks):
249 start_idx = 0
250 except (KeyError,ValueError):
251 start_idx = 0
252 for idx in range(start_idx,len(nicks)) + range(0,start_idx):
253 if nicks[idx].lower().startswith(start.lower()):
254 completion_data['last_nick'] = nicks[idx]
255 return text[:space+1] + nicks[idx] + (': ' if space < 0 else '')
256 return text
257
258
259 294
260 def plug_profile(self, profile_key='@DEFAULT@'): 295 def plug_profile(self, profile_key='@DEFAULT@'):
261 self.loop.widget = self.__buildMainWidget() 296 self.loop.widget = self.__buildMainWidget()
262 self.redraw() 297 self.redraw()
263 QuickApp.plug_profile(self, profile_key) 298 QuickApp.plug_profile(self, profile_key)
317 contact = contact_list.getContact() 352 contact = contact_list.getContact()
318 if contact: 353 if contact:
319 assert(len(self.center_part.widget_list)==2) 354 assert(len(self.center_part.widget_list)==2)
320 self.center_part.widget_list[1] = self.chat_wins[contact] 355 self.center_part.widget_list[1] = self.chat_wins[contact]
321 self.menu_roller.addMenu(_('Chat menu'), self.chat_wins[contact].getMenu()) 356 self.menu_roller.addMenu(_('Chat menu'), self.chat_wins[contact].getMenu())
322
323 def onTextEntered(self, editBar):
324 """Called when text is entered in the main edit bar"""
325 if self.mode == 'INSERTION':
326 contact = self.contact_list.getContact() ###Based on the fact that there is currently only one contact selectableat once
327 if contact:
328 chat = self.chat_wins[contact]
329 try:
330 self.sendMessage(contact,
331 editBar.get_edit_text(),
332 mess_type = "groupchat" if chat.type == 'group' else "chat",
333 profile_key=self.profile)
334 except:
335 self.notify(_("Error while sending message"))
336 editBar.set_edit_text('')
337 elif self.mode == 'COMMAND':
338 self.commandHandler(editBar)
339 357
340 def newMessage(self, from_jid, to_jid, msg, _type, extra, profile): 358 def newMessage(self, from_jid, to_jid, msg, _type, extra, profile):
341 QuickApp.newMessage(self, from_jid, to_jid, msg, _type, extra, profile) 359 QuickApp.newMessage(self, from_jid, to_jid, msg, _type, extra, profile)
342 360
343 if not from_jid in self.contact_list and from_jid.short != self.profiles[profile]['whoami'].short: 361 if not from_jid in self.contact_list and from_jid.short != self.profiles[profile]['whoami'].short:
574 ui.show('window') 592 ui.show('window')
575 def failure(error): 593 def failure(error):
576 self.showPopUp(sat_widgets.Alert(_("Error"), _("Can't get search UI"), ok_cb=self.removePopUp)) 594 self.showPopUp(sat_widgets.Alert(_("Error"), _("Can't get search UI"), ok_cb=self.removePopUp))
577 self.bridge.searchRequest(search_jid, dict(data), self.profile, callback=success, errback=failure) 595 self.bridge.searchRequest(search_jid, dict(data), self.profile, callback=success, errback=failure)
578 596
597 def chatStateReceived(self, from_jid_s, state, profile):
598 """Signal observer to display a contact chat state
599 @param from_jid_s: contact who sent his new state
600 @state: state
601 @profile: current profile
602 """
603 if not self.check_profile(profile):
604 return
605
606 if from_jid_s == "@ALL@":
607 for win in self.chat_wins:
608 self.chat_wins[win].updateChatState(state)
609 return
610
611 from_bare = JID(from_jid_s).short
612 if from_bare in self.chat_wins:
613 self.chat_wins[from_bare].updateChatState(state)
614
579 sat = PrimitivusApp() 615 sat = PrimitivusApp()
580 sat.start() 616 sat.start()
581 617