Mercurial > libervia-desktop-kivy
annotate cagou/plugins/plugin_wid_contact_list.py @ 354:aa860c10acfc
chat: new chat selector:
Using the new ScreenManager feature, a widget to select a chat to display is shown when a
user opens the chat (except if an entity jid is specified, in which case it opens directly
the Chat widget), or when user presses ESC.
When on ChatSelector, pressing ESC brings to the root widget (i.e. default widget).
The ChatSelect is a first draft, it is planned to show opened chats, rooms, and a way to
create new chats.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 17 Jan 2020 18:44:35 +0100 |
parents | e2b51663d8b8 |
children | 9c6fe392d623 |
rev | line source |
---|---|
9 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
282 | 5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) |
9 | 6 |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 from sat.core import log as logging | |
22 log = logging.getLogger(__name__) | |
219 | 23 from cagou.core.constants import Const as C |
322
e2b51663d8b8
core, android: new share widget + added Cagou to "share" menu:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
24 from ..core.common import ContactItem |
14 | 25 from sat.core.i18n import _ |
9 | 26 from sat_frontends.quick_frontend.quick_contact_list import QuickContactList |
22 | 27 from sat_frontends.tools import jid |
219 | 28 from cagou.core.utils import FilterBehavior |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
29 from cagou.core.menu import SideMenu, TouchMenuBehaviour, TouchMenuItemBehaviour |
9 | 30 from kivy import properties |
15
56838ad5c84b
files reorganisation, cagou is now launched with python2 cagou.py in src/
Goffi <goffi@goffi.org>
parents:
14
diff
changeset
|
31 from cagou.core import cagou_widget |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
32 from cagou import G |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
33 from functools import partial |
219 | 34 import bisect |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
35 import re |
9 | 36 |
37 | |
14 | 38 PLUGIN_INFO = { |
312 | 39 "name": _("contacts"), |
14 | 40 "main": "ContactList", |
312 | 41 "description": _("list of contacts"), |
42 "icon_medium": "{media}/icons/muchoslava/png/contact_list_no_border_blue_44.png" | |
14 | 43 } |
44 | |
45 | |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
46 class AddContactMenu(SideMenu): |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
47 profile = properties.StringProperty() |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
48 size_hint_close = (1, 0) |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
49 size_hint_open = (1, 0.5) |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
50 |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
51 def __init__(self, **kwargs): |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
52 super(AddContactMenu, self).__init__(**kwargs) |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
53 if self.profile is None: |
312 | 54 log.warning(_("profile not set in AddContactMenu")) |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
55 self.profile = next(iter(G.host.profiles)) |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
56 |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
57 def addContact(self, contact_jid): |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
58 """Actually add the contact |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
59 |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
60 @param contact_jid(unicode): jid of the contact to add |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
61 """ |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
62 self.hide() |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
63 contact_jid = contact_jid.strip() |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
64 # FIXME: trivial jid verification |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
65 if not contact_jid or not re.match(r"[^@ ]+@[^@ ]+", contact_jid): |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
66 return |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
67 contact_jid = jid.JID(contact_jid).bare |
312 | 68 G.host.bridge.addContact(str(contact_jid), |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
69 self.profile, |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
70 callback=lambda: G.host.addNote( |
312 | 71 _("contact request"), |
72 _("a contact request has been sent to {contact_jid}").format( | |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
73 contact_jid=contact_jid)), |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
74 errback=partial(G.host.errback, |
312 | 75 title=_("can't add contact"), |
76 message=_("error while trying to add contact: {msg}"))) | |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
77 |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
78 |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
79 class DelContactMenu(SideMenu): |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
80 size_hint_close = (1, 0) |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
81 size_hint_open = (1, 0.5) |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
82 |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
83 def __init__(self, contact_item, **kwargs): |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
84 self.contact_item = contact_item |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
85 super(DelContactMenu, self).__init__(**kwargs) |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
86 |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
87 def do_delete_contact(self): |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
88 self.hide() |
312 | 89 G.host.bridge.delContact(str(self.contact_item.jid.bare), |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
90 self.contact_item.profile, |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
91 callback=lambda: G.host.addNote( |
312 | 92 _("contact removed"), |
93 _("{contact_jid} has been removed from your contacts list").format( | |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
94 contact_jid=self.contact_item.jid.bare)), |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
95 errback=partial(G.host.errback, |
312 | 96 title=_("can't remove contact"), |
97 message=_("error while trying to remove contact: {msg}"))) | |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
98 |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
99 |
322
e2b51663d8b8
core, android: new share widget + added Cagou to "share" menu:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
100 class CLContactItem(TouchMenuItemBehaviour, ContactItem): |
9 | 101 |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
102 def do_item_action(self, touch): |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
103 assert self.profile |
219 | 104 # XXX: for now clicking on an item launch the corresponding Chat widget |
105 # behaviour should change in the future | |
312 | 106 G.host.doAction('chat', jid.JID(self.jid), [self.profile]) |
22 | 107 |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
108 def getMenuChoices(self): |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
109 choices = [] |
312 | 110 choices.append(dict(text=_('delete'), |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
111 index=len(choices)+1, |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
112 callback=self.main_wid.removeContact)) |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
113 return choices |
22 | 114 |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
115 |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
116 class ContactList(QuickContactList, cagou_widget.CagouWidget, FilterBehavior, |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
117 TouchMenuBehaviour): |
219 | 118 float_layout = properties.ObjectProperty() |
119 layout = properties.ObjectProperty() | |
9 | 120 |
121 def __init__(self, host, target, profiles): | |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
122 QuickContactList.__init__(self, G.host, profiles) |
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
123 cagou_widget.CagouWidget.__init__(self) |
219 | 124 FilterBehavior.__init__(self) |
125 self._wid_map = {} # (profile, bare_jid) to widget map | |
17
5c9feaa060a5
contact list: added call to the new postInit method
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
126 self.postInit() |
219 | 127 if len(self.profiles) != 1: |
128 raise NotImplementedError('multi profiles is not implemented yet') | |
129 self.update(profile=next(iter(self.profiles))) | |
9 | 130 |
221
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
131 def addContactMenu(self): |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
132 """Show the "add a contact" menu""" |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
133 # FIXME: for now we add contact to the first profile we find |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
134 profile = next(iter(self.profiles)) |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
135 AddContactMenu(profile=profile).show() |
e1a385a791cc
plugin contact list: implemented contact addition
Goffi <goffi@goffi.org>
parents:
219
diff
changeset
|
136 |
223
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
137 def removeContact(self, menu_label): |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
138 item = self.menu_item |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
139 self.clear_menu() |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
140 DelContactMenu(contact_item=item).show() |
9e5f9f0cee48
plugin contact list: use new TouchMenuBehaviour to implement contact deletion
Goffi <goffi@goffi.org>
parents:
221
diff
changeset
|
141 |
110
34dfe0e32064
contact list: text entered in header input do filtering in shown contacts
Goffi <goffi@goffi.org>
parents:
90
diff
changeset
|
142 def onHeaderInputComplete(self, wid, text): |
219 | 143 self.do_filter(self.layout.children, |
144 text, | |
145 lambda c: c.jid, | |
146 width_cb=lambda c: c.base_width, | |
147 height_cb=lambda c: c.minimum_height, | |
148 ) | |
149 | |
150 def _addContactItem(self, bare_jid, profile): | |
322
e2b51663d8b8
core, android: new share widget + added Cagou to "share" menu:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
151 """Create a new CLContactItem instance, and add it |
110
34dfe0e32064
contact list: text entered in header input do filtering in shown contacts
Goffi <goffi@goffi.org>
parents:
90
diff
changeset
|
152 |
219 | 153 item will be added in a sorted position |
154 @param bare_jid(jid.JID): entity bare JID | |
155 @param profile(unicode): profile where the contact is | |
156 """ | |
157 data = G.host.contact_lists[profile].getItem(bare_jid) | |
322
e2b51663d8b8
core, android: new share widget + added Cagou to "share" menu:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
158 wid = CLContactItem(profile=profile, data=data, jid=bare_jid, main_wid=self) |
219 | 159 child_jids = [c.jid for c in reversed(self.layout.children)] |
160 idx = bisect.bisect_right(child_jids, bare_jid) | |
161 self.layout.add_widget(wid, -idx) | |
162 self._wid_map[(profile, bare_jid)] = wid | |
9 | 163 |
164 def update(self, entities=None, type_=None, profile=None): | |
50
c45d6e9ec731
contact list: fixed contact list display
Goffi <goffi@goffi.org>
parents:
39
diff
changeset
|
165 log.debug("update: %s %s %s" % (entities, type_, profile)) |
219 | 166 if type_ == None or type_ == C.UPDATE_STRUCTURE: |
167 log.debug("full contact list update") | |
168 self.layout.clear_widgets() | |
312 | 169 for bare_jid, data in self.items_sorted.items(): |
322
e2b51663d8b8
core, android: new share widget + added Cagou to "share" menu:
Goffi <goffi@goffi.org>
parents:
312
diff
changeset
|
170 wid = CLContactItem(profile=profile, data=data, jid=bare_jid, main_wid=self) |
219 | 171 self.layout.add_widget(wid) |
172 self._wid_map[(profile, bare_jid)] = wid | |
173 elif type_ == C.UPDATE_MODIFY: | |
174 for entity in entities: | |
175 entity_bare = entity.bare | |
176 wid = self._wid_map[(profile, entity_bare)] | |
177 wid.data = G.host.contact_lists[profile].getItem(entity_bare) | |
178 elif type_ == C.UPDATE_ADD: | |
179 for entity in entities: | |
180 self._addContactItem(entity.bare, profile) | |
181 elif type_ == C.UPDATE_DELETE: | |
182 for entity in entities: | |
183 try: | |
184 self.layout.remove_widget(self._wid_map.pop((profile, entity.bare))) | |
185 except KeyError: | |
186 log.debug("entity not found: {entity}".format(entity=entity.bare)) | |
187 else: | |
188 log.debug("update type not handled: {update_type}".format(update_type=type_)) |