Mercurial > libervia-desktop-kivy
comparison src/cagou/plugins/plugin_wid_chat.py @ 109:7631325e11f4
chat: added completion of header's input, any entity in cache containing the entered text is shown
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 15 Jan 2017 21:21:29 +0100 |
parents | 9909ed7a7a20 |
children | c3952922ca56 |
comparison
equal
deleted
inserted
replaced
108:953ddf817b8a | 109:7631325e11f4 |
---|---|
30 from sat_frontends.quick_frontend import quick_widgets | 30 from sat_frontends.quick_frontend import quick_widgets |
31 from sat_frontends.quick_frontend import quick_chat | 31 from sat_frontends.quick_frontend import quick_chat |
32 from sat_frontends.tools import jid | 32 from sat_frontends.tools import jid |
33 from cagou.core import cagou_widget | 33 from cagou.core import cagou_widget |
34 from cagou.core.image import Image | 34 from cagou.core.image import Image |
35 from cagou.core.common import JidWidget | |
36 from kivy.uix.dropdown import DropDown | |
35 from cagou import G | 37 from cagou import G |
36 | 38 |
37 | 39 |
38 PLUGIN_INFO = { | 40 PLUGIN_INFO = { |
39 "name": _(u"chat"), | 41 "name": _(u"chat"), |
129 self.header_input.hint_text = u"{}".format(target) | 131 self.header_input.hint_text = u"{}".format(target) |
130 self.host.addListener('progressError', self.onProgressError, profiles) | 132 self.host.addListener('progressError', self.onProgressError, profiles) |
131 self.host.addListener('progressFinished', self.onProgressFinished, profiles) | 133 self.host.addListener('progressFinished', self.onProgressFinished, profiles) |
132 self._waiting_pids = {} # waiting progress ids | 134 self._waiting_pids = {} # waiting progress ids |
133 self.postInit() | 135 self.postInit() |
136 # completion attribtues | |
137 self._hi_comp_data = None | |
138 self._hi_comp_last = None | |
139 self._hi_comp_dropdown = DropDown() | |
140 self._hi_comp_allowed = True | |
134 | 141 |
135 @classmethod | 142 @classmethod |
136 def factory(cls, plugin_info, target, profiles): | 143 def factory(cls, plugin_info, target, profiles): |
137 profiles = list(profiles) | 144 profiles = list(profiles) |
138 if len(profiles) > 1: | 145 if len(profiles) > 1: |
139 raise NotImplementedError(u"Multi-profiles is not available yet for chat") | 146 raise NotImplementedError(u"Multi-profiles is not available yet for chat") |
140 if target is None: | 147 if target is None: |
141 target = G.host.profiles[profiles[0]].whoami | 148 target = G.host.profiles[profiles[0]].whoami |
142 return G.host.widgets.getOrCreateWidget(cls, target, on_new_widget=None, on_existing_widget=C.WIDGET_RECREATE, profiles=profiles) | 149 return G.host.widgets.getOrCreateWidget(cls, target, on_new_widget=None, on_existing_widget=C.WIDGET_RECREATE, profiles=profiles) |
150 | |
151 ## header ## | |
152 | |
153 def changeWidget(self, jid_): | |
154 """change current widget for a new one with given jid | |
155 | |
156 @param jid_(jid.JID): jid of the widget to create | |
157 """ | |
158 plugin_info = G.host.getPluginInfo(main=Chat) | |
159 factory = plugin_info['factory'] | |
160 G.host.switchWidget(self, factory(plugin_info, jid_, profiles=[self.profile])) | |
161 self.header_input.text = '' | |
162 | |
163 def onHeaderInput(self): | |
164 text = self.header_input.text.strip() | |
165 try: | |
166 if text.count(u'@') != 1 or text.count(u' '): | |
167 raise ValueError | |
168 jid_ = jid.JID(text) | |
169 except ValueError: | |
170 log.info(u"entered text is not a jid") | |
171 return | |
172 | |
173 def discoCb(disco): | |
174 # TODO: check if plugin XEP-0045 is activated | |
175 if "conference" in [i[0] for i in disco[1]]: | |
176 G.host.bridge.mucJoin(unicode(jid_), "", "", self.profile, callback=self._mucJoinCb, errback=self._mucJoinEb) | |
177 else: | |
178 self.changeWidget(jid_) | |
179 | |
180 def discoEb(failure): | |
181 log.warning(u"Disco failure, ignore this text: {}".format(failure)) | |
182 | |
183 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb) | |
184 | |
185 def onHeaderInputCompleted(self, input_wid, completed_text): | |
186 self._hi_comp_allowed = False | |
187 input_wid.text = completed_text | |
188 self._hi_comp_allowed = True | |
189 self._hi_comp_dropdown.dismiss() | |
190 self.onHeaderInput() | |
191 | |
192 def onHeaderInputComplete(self, wid, text): | |
193 if not self._hi_comp_allowed: | |
194 return | |
195 text = text.lstrip() | |
196 if not text: | |
197 self._hi_comp_data = None | |
198 self._hi_comp_last = None | |
199 return | |
200 | |
201 profile = list(self.profiles)[0] | |
202 | |
203 if self._hi_comp_data is None: | |
204 # first completion, we build the initial list | |
205 comp_data = self._hi_comp_data = [] | |
206 self._hi_comp_last = '' | |
207 for jid_, jid_data in G.host.contact_lists[profile].all_iter: | |
208 comp_data.append((jid_, jid_data)) | |
209 comp_data.sort(key=lambda datum: datum[0]) | |
210 else: | |
211 comp_data = self._hi_comp_data | |
212 | |
213 # XXX: dropdown is rebuilt each time backspace is pressed or if the text is changed, | |
214 # it works OK, but some optimisation may be done here | |
215 dropdown = self._hi_comp_dropdown | |
216 | |
217 if not text.startswith(self._hi_comp_last) or not self._hi_comp_last: | |
218 # text has changed or backspace has been pressed, we restart | |
219 dropdown.clear_widgets() | |
220 | |
221 for jid_, jid_data in comp_data: | |
222 nick = jid_data.get(u'nick', u'') | |
223 if text in jid_.bare or text in nick.lower(): | |
224 btn = JidWidget( | |
225 jid = jid_.bare, | |
226 profile = profile, | |
227 size_hint = (0.5, None), | |
228 nick = nick, | |
229 on_release=lambda dummy, txt=jid_.bare: self.onHeaderInputCompleted(wid, txt) | |
230 ) | |
231 dropdown.add_widget(btn) | |
232 else: | |
233 # more chars, we continue completion by removing unwanted widgets | |
234 to_remove = [] | |
235 for c in dropdown.children[0].children: | |
236 if text not in c.jid and text not in (c.nick or ''): | |
237 to_remove.append(c) | |
238 for c in to_remove: | |
239 dropdown.remove_widget(c) | |
240 | |
241 dropdown.open(wid) | |
242 self._hi_comp_last = text | |
143 | 243 |
144 def messageDataConverter(self, idx, mess_id): | 244 def messageDataConverter(self, idx, mess_id): |
145 return {"mess_data": self.messages[mess_id]} | 245 return {"mess_data": self.messages[mess_id]} |
146 | 246 |
147 def _onHistoryPrinted(self): | 247 def _onHistoryPrinted(self): |
236 self.changeWidget(jid_) | 336 self.changeWidget(jid_) |
237 | 337 |
238 def _mucJoinEb(self, failure): | 338 def _mucJoinEb(self, failure): |
239 log.warning(u"Can't join room: {}".format(failure)) | 339 log.warning(u"Can't join room: {}".format(failure)) |
240 | 340 |
241 def changeWidget(self, jid_): | |
242 """change current widget for a new one with given jid | |
243 | |
244 @param jid_(jid.JID): jid of the widget to create | |
245 """ | |
246 plugin_info = G.host.getPluginInfo(main=Chat) | |
247 factory = plugin_info['factory'] | |
248 G.host.switchWidget(self, factory(plugin_info, jid_, profiles=[self.profile])) | |
249 self.header_input.text = '' | |
250 | |
251 def onHeaderInput(self): | |
252 text = self.header_input.text.strip() | |
253 try: | |
254 if text.count(u'@') != 1 or text.count(u' '): | |
255 raise ValueError | |
256 jid_ = jid.JID(text) | |
257 except ValueError: | |
258 log.info(u"entered text is not a jid") | |
259 return | |
260 | |
261 def discoCb(disco): | |
262 # TODO: check if plugin XEP-0045 is activated | |
263 if "conference" in [i[0] for i in disco[1]]: | |
264 G.host.bridge.mucJoin(unicode(jid_), "", "", self.profile, callback=self._mucJoinCb, errback=self._mucJoinEb) | |
265 else: | |
266 self.changeWidget(jid_) | |
267 | |
268 def discoEb(failure): | |
269 log.warning(u"Disco failure, ignore this text: {}".format(failure)) | |
270 | |
271 G.host.bridge.discoInfos(jid_.domain, self.profile, callback=discoCb, errback=discoEb) | |
272 | |
273 def _onDelete(self): | 341 def _onDelete(self): |
274 self.host.removeListener('progressFinished', self.onProgressFinished) | 342 self.host.removeListener('progressFinished', self.onProgressFinished) |
275 self.host.removeListener('progressError', self.onProgressError) | 343 self.host.removeListener('progressError', self.onProgressError) |
276 return super(Chat, self).onDelete() | 344 return super(Chat, self).onDelete() |
277 | 345 |