comparison sat/stdui/ui_contact_list.py @ 4037:524856bd7b19

massive refactoring to switch from camelCase to snake_case: historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a pre-PEP8 code, to use the same coding style as in Twisted. However, snake_case is more readable and it's better to follow PEP8 best practices, so it has been decided to move on full snake_case. Because Libervia has a huge codebase, this ended with a ugly mix of camelCase and snake_case. To fix that, this patch does a big refactoring by renaming every function and method (including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case. This is a massive change, and may result in some bugs.
author Goffi <goffi@goffi.org>
date Sat, 08 Apr 2023 13:54:42 +0200
parents be6d91572633
children
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
27 class ContactList(object): 27 class ContactList(object):
28 """Add, update and remove contacts.""" 28 """Add, update and remove contacts."""
29 29
30 def __init__(self, host): 30 def __init__(self, host):
31 self.host = host 31 self.host = host
32 self.__add_id = host.registerCallback(self._addContact, with_data=True) 32 self.__add_id = host.register_callback(self._add_contact, with_data=True)
33 self.__update_id = host.registerCallback(self._updateContact, with_data=True) 33 self.__update_id = host.register_callback(self._update_contact, with_data=True)
34 self.__confirm_delete_id = host.registerCallback( 34 self.__confirm_delete_id = host.register_callback(
35 self._getConfirmRemoveXMLUI, with_data=True 35 self._get_confirm_remove_xmlui, with_data=True
36 ) 36 )
37 37
38 host.importMenu( 38 host.import_menu(
39 (D_("Contacts"), D_("Add contact")), 39 (D_("Contacts"), D_("Add contact")),
40 self._getAddDialogXMLUI, 40 self._get_add_dialog_xmlui,
41 security_limit=2, 41 security_limit=2,
42 help_string=D_("Add contact"), 42 help_string=D_("Add contact"),
43 ) 43 )
44 host.importMenu( 44 host.import_menu(
45 (D_("Contacts"), D_("Update contact")), 45 (D_("Contacts"), D_("Update contact")),
46 self._getUpdateDialogXMLUI, 46 self._get_update_dialog_xmlui,
47 security_limit=2, 47 security_limit=2,
48 help_string=D_("Update contact"), 48 help_string=D_("Update contact"),
49 ) 49 )
50 host.importMenu( 50 host.import_menu(
51 (D_("Contacts"), D_("Remove contact")), 51 (D_("Contacts"), D_("Remove contact")),
52 self._getRemoveDialogXMLUI, 52 self._get_remove_dialog_xmlui,
53 security_limit=2, 53 security_limit=2,
54 help_string=D_("Remove contact"), 54 help_string=D_("Remove contact"),
55 ) 55 )
56 56
57 # FIXME: a plugin should not be used here, and current profile's jid host would be better than installation wise host 57 # FIXME: a plugin should not be used here, and current profile's jid host would be better than installation wise host
58 if "MISC-ACCOUNT" in self.host.plugins: 58 if "MISC-ACCOUNT" in self.host.plugins:
59 self.default_host = self.host.plugins["MISC-ACCOUNT"].getNewAccountDomain() 59 self.default_host = self.host.plugins["MISC-ACCOUNT"].account_domain_new_get()
60 else: 60 else:
61 self.default_host = "example.net" 61 self.default_host = "example.net"
62 62
63 def getContacts(self, profile): 63 def contacts_get(self, profile):
64 """Return a sorted list of the contacts for that profile 64 """Return a sorted list of the contacts for that profile
65 65
66 @param profile: %(doc_profile)s 66 @param profile: %(doc_profile)s
67 @return: list[string] 67 @return: list[string]
68 """ 68 """
69 client = self.host.getClient(profile) 69 client = self.host.get_client(profile)
70 ret = [contact.full() for contact in client.roster.getJids()] 70 ret = [contact.full() for contact in client.roster.get_jids()]
71 ret.sort() 71 ret.sort()
72 return ret 72 return ret
73 73
74 def getGroups(self, new_groups=None, profile=C.PROF_KEY_NONE): 74 def get_groups(self, new_groups=None, profile=C.PROF_KEY_NONE):
75 """Return a sorted list of the groups for that profile 75 """Return a sorted list of the groups for that profile
76 76
77 @param new_group (list): add these groups to the existing ones 77 @param new_group (list): add these groups to the existing ones
78 @param profile: %(doc_profile)s 78 @param profile: %(doc_profile)s
79 @return: list[string] 79 @return: list[string]
80 """ 80 """
81 client = self.host.getClient(profile) 81 client = self.host.get_client(profile)
82 ret = client.roster.getGroups() 82 ret = client.roster.get_groups()
83 ret.sort() 83 ret.sort()
84 ret.extend([group for group in new_groups if group not in ret]) 84 ret.extend([group for group in new_groups if group not in ret])
85 return ret 85 return ret
86 86
87 def getGroupsOfContact(self, user_jid_s, profile): 87 def get_groups_of_contact(self, user_jid_s, profile):
88 """Return all the groups of the given contact 88 """Return all the groups of the given contact
89 89
90 @param user_jid_s (string) 90 @param user_jid_s (string)
91 @param profile: %(doc_profile)s 91 @param profile: %(doc_profile)s
92 @return: list[string] 92 @return: list[string]
93 """ 93 """
94 client = self.host.getClient(profile) 94 client = self.host.get_client(profile)
95 return client.roster.getItem(jid.JID(user_jid_s)).groups 95 return client.roster.get_item(jid.JID(user_jid_s)).groups
96 96
97 def getGroupsOfAllContacts(self, profile): 97 def get_groups_of_all_contacts(self, profile):
98 """Return a mapping between the contacts and their groups 98 """Return a mapping between the contacts and their groups
99 99
100 @param profile: %(doc_profile)s 100 @param profile: %(doc_profile)s
101 @return: dict (key: string, value: list[string]): 101 @return: dict (key: string, value: list[string]):
102 - key: the JID userhost 102 - key: the JID userhost
103 - value: list of groups 103 - value: list of groups
104 """ 104 """
105 client = self.host.getClient(profile) 105 client = self.host.get_client(profile)
106 return {item.jid.userhost(): item.groups for item in client.roster.getItems()} 106 return {item.jid.userhost(): item.groups for item in client.roster.get_items()}
107 107
108 def _data2elts(self, data): 108 def _data2elts(self, data):
109 """Convert a contacts data dict to minidom Elements 109 """Convert a contacts data dict to minidom Elements
110 110
111 @param data (dict) 111 @param data (dict)
120 value_elt.setAttribute("name", value) 120 value_elt.setAttribute("name", value)
121 key_elt.childNodes.append(value_elt) 121 key_elt.childNodes.append(value_elt)
122 elts.append(key_elt) 122 elts.append(key_elt)
123 return elts 123 return elts
124 124
125 def getDialogXMLUI(self, options, data, profile): 125 def get_dialog_xmlui(self, options, data, profile):
126 """Generic method to return the XMLUI dialog for adding or updating a contact 126 """Generic method to return the XMLUI dialog for adding or updating a contact
127 127
128 @param options (dict): parameters for the dialog, with the keys: 128 @param options (dict): parameters for the dialog, with the keys:
129 - 'id': the menu callback id 129 - 'id': the menu callback id
130 - 'title': deferred localized string 130 - 'title': deferred localized string
139 form_ui.addDivider("dash") 139 form_ui.addDivider("dash")
140 140
141 form_ui.addText(options["contact_text"]) 141 form_ui.addText(options["contact_text"])
142 if options["id"] == self.__add_id: 142 if options["id"] == self.__add_id:
143 contact = data.get( 143 contact = data.get(
144 xml_tools.formEscape("contact_jid"), "@%s" % self.default_host 144 xml_tools.form_escape("contact_jid"), "@%s" % self.default_host
145 ) 145 )
146 form_ui.addString("contact_jid", value=contact) 146 form_ui.addString("contact_jid", value=contact)
147 elif options["id"] == self.__update_id: 147 elif options["id"] == self.__update_id:
148 contacts = self.getContacts(profile) 148 contacts = self.contacts_get(profile)
149 list_ = form_ui.addList("contact_jid", options=contacts, selected=contacts[0]) 149 list_ = form_ui.addList("contact_jid", options=contacts, selected=contacts[0])
150 elts = self._data2elts(self.getGroupsOfAllContacts(profile)) 150 elts = self._data2elts(self.get_groups_of_all_contacts(profile))
151 list_.setInternalCallback( 151 list_.set_internal_callback(
152 "groups_of_contact", fields=["contact_jid", "groups_list"], data_elts=elts 152 "groups_of_contact", fields=["contact_jid", "groups_list"], data_elts=elts
153 ) 153 )
154 154
155 form_ui.addDivider("blank") 155 form_ui.addDivider("blank")
156 156
158 selected_groups = [] 158 selected_groups = []
159 if "selected_groups" in data: 159 if "selected_groups" in data:
160 selected_groups = data["selected_groups"] 160 selected_groups = data["selected_groups"]
161 elif options["id"] == self.__update_id: 161 elif options["id"] == self.__update_id:
162 try: 162 try:
163 selected_groups = self.getGroupsOfContact(contacts[0], profile) 163 selected_groups = self.get_groups_of_contact(contacts[0], profile)
164 except IndexError: 164 except IndexError:
165 pass 165 pass
166 groups = self.getGroups(selected_groups, profile) 166 groups = self.get_groups(selected_groups, profile)
167 form_ui.addList( 167 form_ui.addList(
168 "groups_list", options=groups, selected=selected_groups, styles=["multi"] 168 "groups_list", options=groups, selected=selected_groups, styles=["multi"]
169 ) 169 )
170 170
171 adv_list = form_ui.changeContainer("advanced_list", columns=3, selectable="no") 171 adv_list = form_ui.change_container("advanced_list", columns=3, selectable="no")
172 form_ui.addLabel(D_("Add group")) 172 form_ui.addLabel(D_("Add group"))
173 form_ui.addString("add_group") 173 form_ui.addString("add_group")
174 button = form_ui.addButton("", value=D_("Add")) 174 button = form_ui.addButton("", value=D_("Add"))
175 button.setInternalCallback("move", fields=["add_group", "groups_list"]) 175 button.set_internal_callback("move", fields=["add_group", "groups_list"])
176 adv_list.end() 176 adv_list.end()
177 177
178 form_ui.addDivider("blank") 178 form_ui.addDivider("blank")
179 return {"xmlui": form_ui.toXml()} 179 return {"xmlui": form_ui.toXml()}
180 180
181 def _getAddDialogXMLUI(self, data, profile): 181 def _get_add_dialog_xmlui(self, data, profile):
182 """Get the dialog for adding contact 182 """Get the dialog for adding contact
183 183
184 @param data (dict) 184 @param data (dict)
185 @param profile: %(doc_profile)s 185 @param profile: %(doc_profile)s
186 @return dict 186 @return dict
188 options = { 188 options = {
189 "id": self.__add_id, 189 "id": self.__add_id,
190 "title": D_("Add contact"), 190 "title": D_("Add contact"),
191 "contact_text": D_("New contact identifier (JID):"), 191 "contact_text": D_("New contact identifier (JID):"),
192 } 192 }
193 return self.getDialogXMLUI(options, {}, profile) 193 return self.get_dialog_xmlui(options, {}, profile)
194 194
195 def _getUpdateDialogXMLUI(self, data, profile): 195 def _get_update_dialog_xmlui(self, data, profile):
196 """Get the dialog for updating contact 196 """Get the dialog for updating contact
197 197
198 @param data (dict) 198 @param data (dict)
199 @param profile: %(doc_profile)s 199 @param profile: %(doc_profile)s
200 @return dict 200 @return dict
201 """ 201 """
202 if not self.getContacts(profile): 202 if not self.contacts_get(profile):
203 _dialog = xml_tools.XMLUI("popup", title=D_("Nothing to update")) 203 _dialog = xml_tools.XMLUI("popup", title=D_("Nothing to update"))
204 _dialog.addText(_("Your contact list is empty.")) 204 _dialog.addText(_("Your contact list is empty."))
205 return {"xmlui": _dialog.toXml()} 205 return {"xmlui": _dialog.toXml()}
206 206
207 options = { 207 options = {
208 "id": self.__update_id, 208 "id": self.__update_id,
209 "title": D_("Update contact"), 209 "title": D_("Update contact"),
210 "contact_text": D_("Which contact do you want to update?"), 210 "contact_text": D_("Which contact do you want to update?"),
211 } 211 }
212 return self.getDialogXMLUI(options, {}, profile) 212 return self.get_dialog_xmlui(options, {}, profile)
213 213
214 def _getRemoveDialogXMLUI(self, data, profile): 214 def _get_remove_dialog_xmlui(self, data, profile):
215 """Get the dialog for removing contact 215 """Get the dialog for removing contact
216 216
217 @param data (dict) 217 @param data (dict)
218 @param profile: %(doc_profile)s 218 @param profile: %(doc_profile)s
219 @return dict 219 @return dict
220 """ 220 """
221 if not self.getContacts(profile): 221 if not self.contacts_get(profile):
222 _dialog = xml_tools.XMLUI("popup", title=D_("Nothing to delete")) 222 _dialog = xml_tools.XMLUI("popup", title=D_("Nothing to delete"))
223 _dialog.addText(_("Your contact list is empty.")) 223 _dialog.addText(_("Your contact list is empty."))
224 return {"xmlui": _dialog.toXml()} 224 return {"xmlui": _dialog.toXml()}
225 225
226 form_ui = xml_tools.XMLUI( 226 form_ui = xml_tools.XMLUI(
227 "form", 227 "form",
228 title=D_("Who do you want to remove from your contacts?"), 228 title=D_("Who do you want to remove from your contacts?"),
229 submit_id=self.__confirm_delete_id, 229 submit_id=self.__confirm_delete_id,
230 ) 230 )
231 form_ui.addList("contact_jid", options=self.getContacts(profile)) 231 form_ui.addList("contact_jid", options=self.contacts_get(profile))
232 return {"xmlui": form_ui.toXml()} 232 return {"xmlui": form_ui.toXml()}
233 233
234 def _getConfirmRemoveXMLUI(self, data, profile): 234 def _get_confirm_remove_xmlui(self, data, profile):
235 """Get the confirmation dialog for removing contact 235 """Get the confirmation dialog for removing contact
236 236
237 @param data (dict) 237 @param data (dict)
238 @param profile: %(doc_profile)s 238 @param profile: %(doc_profile)s
239 @return dict 239 @return dict
240 """ 240 """
241 if C.bool(data.get("cancelled", "false")): 241 if C.bool(data.get("cancelled", "false")):
242 return {} 242 return {}
243 contact = data[xml_tools.formEscape("contact_jid")] 243 contact = data[xml_tools.form_escape("contact_jid")]
244 244
245 def delete_cb(data, profile): 245 def delete_cb(data, profile):
246 if not C.bool(data.get("cancelled", "false")): 246 if not C.bool(data.get("cancelled", "false")):
247 self._deleteContact(jid.JID(contact), profile) 247 self._delete_contact(jid.JID(contact), profile)
248 return {} 248 return {}
249 249
250 delete_id = self.host.registerCallback(delete_cb, with_data=True, one_shot=True) 250 delete_id = self.host.register_callback(delete_cb, with_data=True, one_shot=True)
251 form_ui = xml_tools.XMLUI("form", title=D_("Delete contact"), submit_id=delete_id) 251 form_ui = xml_tools.XMLUI("form", title=D_("Delete contact"), submit_id=delete_id)
252 form_ui.addText( 252 form_ui.addText(
253 D_("Are you sure you want to remove %s from your contact list?") % contact 253 D_("Are you sure you want to remove %s from your contact list?") % contact
254 ) 254 )
255 return {"xmlui": form_ui.toXml()} 255 return {"xmlui": form_ui.toXml()}
256 256
257 def _addContact(self, data, profile): 257 def _add_contact(self, data, profile):
258 """Add the selected contact 258 """Add the selected contact
259 259
260 @param data (dict) 260 @param data (dict)
261 @param profile: %(doc_profile)s 261 @param profile: %(doc_profile)s
262 @return dict 262 @return dict
263 """ 263 """
264 if C.bool(data.get("cancelled", "false")): 264 if C.bool(data.get("cancelled", "false")):
265 return {} 265 return {}
266 contact_jid_s = data[xml_tools.formEscape("contact_jid")] 266 contact_jid_s = data[xml_tools.form_escape("contact_jid")]
267 try: 267 try:
268 contact_jid = jid.JID(contact_jid_s) 268 contact_jid = jid.JID(contact_jid_s)
269 except (RuntimeError, jid.InvalidFormat, AttributeError): 269 except (RuntimeError, jid.InvalidFormat, AttributeError):
270 # TODO: replace '\t' by a constant (see tools.xmlui.XMLUI.onFormSubmitted) 270 # TODO: replace '\t' by a constant (see tools.xmlui.XMLUI.on_form_submitted)
271 data["selected_groups"] = data[xml_tools.formEscape("groups_list")].split( 271 data["selected_groups"] = data[xml_tools.form_escape("groups_list")].split(
272 "\t" 272 "\t"
273 ) 273 )
274 options = { 274 options = {
275 "id": self.__add_id, 275 "id": self.__add_id,
276 "title": D_("Add contact"), 276 "title": D_("Add contact"),
277 "contact_text": D_('Please enter a valid JID (like "contact@%s"):') 277 "contact_text": D_('Please enter a valid JID (like "contact@%s"):')
278 % self.default_host, 278 % self.default_host,
279 } 279 }
280 return self.getDialogXMLUI(options, data, profile) 280 return self.get_dialog_xmlui(options, data, profile)
281 self.host.addContact(contact_jid, profile_key=profile) 281 self.host.contact_add(contact_jid, profile_key=profile)
282 return self._updateContact(data, profile) # after adding, updating 282 return self._update_contact(data, profile) # after adding, updating
283 283
284 def _updateContact(self, data, profile): 284 def _update_contact(self, data, profile):
285 """Update the selected contact 285 """Update the selected contact
286 286
287 @param data (dict) 287 @param data (dict)
288 @param profile: %(doc_profile)s 288 @param profile: %(doc_profile)s
289 @return dict 289 @return dict
290 """ 290 """
291 client = self.host.getClient(profile) 291 client = self.host.get_client(profile)
292 if C.bool(data.get("cancelled", "false")): 292 if C.bool(data.get("cancelled", "false")):
293 return {} 293 return {}
294 contact_jid = jid.JID(data[xml_tools.formEscape("contact_jid")]) 294 contact_jid = jid.JID(data[xml_tools.form_escape("contact_jid")])
295 # TODO: replace '\t' by a constant (see tools.xmlui.XMLUI.onFormSubmitted) 295 # TODO: replace '\t' by a constant (see tools.xmlui.XMLUI.on_form_submitted)
296 groups = data[xml_tools.formEscape("groups_list")].split("\t") 296 groups = data[xml_tools.form_escape("groups_list")].split("\t")
297 self.host.updateContact(client, contact_jid, name="", groups=groups) 297 self.host.contact_update(client, contact_jid, name="", groups=groups)
298 return {} 298 return {}
299 299
300 def _deleteContact(self, contact_jid, profile): 300 def _delete_contact(self, contact_jid, profile):
301 """Delete the selected contact 301 """Delete the selected contact
302 302
303 @param contact_jid (JID) 303 @param contact_jid (JID)
304 @param profile: %(doc_profile)s 304 @param profile: %(doc_profile)s
305 @return dict 305 @return dict
306 """ 306 """
307 self.host.delContact(contact_jid, profile_key=profile) 307 self.host.contact_del(contact_jid, profile_key=profile)
308 return {} 308 return {}