Mercurial > libervia-desktop-kivy
comparison libervia/desktop_kivy/plugins/plugin_wid_contact_list.py @ 493:b3cedbee561d
refactoring: rename `cagou` to `libervia.desktop_kivy` + update imports and names following backend changes
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 18:26:16 +0200 |
parents | cagou/plugins/plugin_wid_contact_list.py@203755bbe0fe |
children |
comparison
equal
deleted
inserted
replaced
492:5114bbb5daa3 | 493:b3cedbee561d |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 #Libervia Desktop-Kivy | |
5 # Copyright (C) 2016-2021 Jérôme Poisson (goffi@goffi.org) | |
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 functools import partial | |
22 import bisect | |
23 import re | |
24 from libervia.backend.core import log as logging | |
25 from libervia.backend.core.i18n import _ | |
26 from libervia.frontends.quick_frontend.quick_contact_list import QuickContactList | |
27 from libervia.frontends.tools import jid | |
28 from kivy import properties | |
29 from libervia.desktop_kivy import G | |
30 from ..core import cagou_widget | |
31 from ..core.constants import Const as C | |
32 from ..core.common import ContactItem | |
33 from ..core.behaviors import FilterBehavior, TouchMenuBehavior, TouchMenuItemBehavior | |
34 from ..core.menu import SideMenu | |
35 | |
36 | |
37 log = logging.getLogger(__name__) | |
38 | |
39 | |
40 PLUGIN_INFO = { | |
41 "name": _("contacts"), | |
42 "main": "ContactList", | |
43 "description": _("list of contacts"), | |
44 "icon_medium": "{media}/icons/muchoslava/png/contact_list_no_border_blue_44.png" | |
45 } | |
46 | |
47 | |
48 class AddContactMenu(SideMenu): | |
49 profile = properties.StringProperty() | |
50 size_hint_close = (1, 0) | |
51 size_hint_open = (1, 0.5) | |
52 | |
53 def __init__(self, **kwargs): | |
54 super(AddContactMenu, self).__init__(**kwargs) | |
55 if self.profile is None: | |
56 log.warning(_("profile not set in AddContactMenu")) | |
57 self.profile = next(iter(G.host.profiles)) | |
58 | |
59 def contact_add(self, contact_jid): | |
60 """Actually add the contact | |
61 | |
62 @param contact_jid(unicode): jid of the contact to add | |
63 """ | |
64 self.hide() | |
65 contact_jid = contact_jid.strip() | |
66 # FIXME: trivial jid verification | |
67 if not contact_jid or not re.match(r"[^@ ]+@[^@ ]+", contact_jid): | |
68 return | |
69 contact_jid = jid.JID(contact_jid).bare | |
70 G.host.bridge.contact_add(str(contact_jid), | |
71 self.profile, | |
72 callback=lambda: G.host.add_note( | |
73 _("contact request"), | |
74 _("a contact request has been sent to {contact_jid}").format( | |
75 contact_jid=contact_jid)), | |
76 errback=partial(G.host.errback, | |
77 title=_("can't add contact"), | |
78 message=_("error while trying to add contact: {msg}"))) | |
79 | |
80 | |
81 class DelContactMenu(SideMenu): | |
82 size_hint_close = (1, 0) | |
83 size_hint_open = (1, 0.5) | |
84 | |
85 def __init__(self, contact_item, **kwargs): | |
86 self.contact_item = contact_item | |
87 super(DelContactMenu, self).__init__(**kwargs) | |
88 | |
89 def do_delete_contact(self): | |
90 self.hide() | |
91 G.host.bridge.contact_del(str(self.contact_item.jid.bare), | |
92 self.contact_item.profile, | |
93 callback=lambda: G.host.add_note( | |
94 _("contact removed"), | |
95 _("{contact_jid} has been removed from your contacts list").format( | |
96 contact_jid=self.contact_item.jid.bare)), | |
97 errback=partial(G.host.errback, | |
98 title=_("can't remove contact"), | |
99 message=_("error while trying to remove contact: {msg}"))) | |
100 | |
101 | |
102 class CLContactItem(TouchMenuItemBehavior, ContactItem): | |
103 | |
104 def do_item_action(self, touch): | |
105 assert self.profile | |
106 # XXX: for now clicking on an item launch the corresponding Chat widget | |
107 # behaviour should change in the future | |
108 G.host.do_action('chat', jid.JID(self.jid), [self.profile]) | |
109 | |
110 def get_menu_choices(self): | |
111 choices = [] | |
112 choices.append(dict(text=_('delete'), | |
113 index=len(choices)+1, | |
114 callback=self.main_wid.remove_contact)) | |
115 return choices | |
116 | |
117 | |
118 class ContactList(QuickContactList, cagou_widget.LiberviaDesktopKivyWidget, FilterBehavior, | |
119 TouchMenuBehavior): | |
120 float_layout = properties.ObjectProperty() | |
121 layout = properties.ObjectProperty() | |
122 use_header_input = True | |
123 | |
124 def __init__(self, host, target, profiles): | |
125 QuickContactList.__init__(self, G.host, profiles) | |
126 cagou_widget.LiberviaDesktopKivyWidget.__init__(self) | |
127 FilterBehavior.__init__(self) | |
128 self._wid_map = {} # (profile, bare_jid) to widget map | |
129 self.post_init() | |
130 if len(self.profiles) != 1: | |
131 raise NotImplementedError('multi profiles is not implemented yet') | |
132 self.update(profile=next(iter(self.profiles))) | |
133 | |
134 def add_contact_menu(self): | |
135 """Show the "add a contact" menu""" | |
136 # FIXME: for now we add contact to the first profile we find | |
137 profile = next(iter(self.profiles)) | |
138 AddContactMenu(profile=profile).show() | |
139 | |
140 def remove_contact(self, menu_label): | |
141 item = self.menu_item | |
142 self.clear_menu() | |
143 DelContactMenu(contact_item=item).show() | |
144 | |
145 def on_header_wid_input_complete(self, wid, text): | |
146 self.do_filter(self.layout, | |
147 text, | |
148 lambda c: c.jid, | |
149 width_cb=lambda c: c.base_width, | |
150 height_cb=lambda c: c.minimum_height, | |
151 ) | |
152 | |
153 def _add_contact_item(self, bare_jid, profile): | |
154 """Create a new CLContactItem instance, and add it | |
155 | |
156 item will be added in a sorted position | |
157 @param bare_jid(jid.JID): entity bare JID | |
158 @param profile(unicode): profile where the contact is | |
159 """ | |
160 data = G.host.contact_lists[profile].get_item(bare_jid) | |
161 wid = CLContactItem(profile=profile, data=data, jid=bare_jid, main_wid=self) | |
162 child_jids = [c.jid for c in reversed(self.layout.children)] | |
163 idx = bisect.bisect_right(child_jids, bare_jid) | |
164 self.layout.add_widget(wid, -idx) | |
165 self._wid_map[(profile, bare_jid)] = wid | |
166 | |
167 def update(self, entities=None, type_=None, profile=None): | |
168 log.debug("update: %s %s %s" % (entities, type_, profile)) | |
169 if type_ == None or type_ == C.UPDATE_STRUCTURE: | |
170 log.debug("full contact list update") | |
171 self.layout.clear_widgets() | |
172 for bare_jid, data in self.items_sorted.items(): | |
173 wid = CLContactItem( | |
174 profile=data['profile'], | |
175 data=data, | |
176 jid=bare_jid, | |
177 main_wid=self, | |
178 ) | |
179 self.layout.add_widget(wid) | |
180 self._wid_map[(profile, bare_jid)] = wid | |
181 elif type_ == C.UPDATE_MODIFY: | |
182 for entity in entities: | |
183 entity_bare = entity.bare | |
184 wid = self._wid_map[(profile, entity_bare)] | |
185 wid.data = G.host.contact_lists[profile].get_item(entity_bare) | |
186 elif type_ == C.UPDATE_ADD: | |
187 for entity in entities: | |
188 self._add_contact_item(entity.bare, profile) | |
189 elif type_ == C.UPDATE_DELETE: | |
190 for entity in entities: | |
191 try: | |
192 self.layout.remove_widget(self._wid_map.pop((profile, entity.bare))) | |
193 except KeyError: | |
194 log.debug("entity not found: {entity}".format(entity=entity.bare)) | |
195 else: | |
196 log.debug("update type not handled: {update_type}".format(update_type=type_)) |