Mercurial > libervia-web
comparison src/browser/sat_browser/contact_group.py @ 600:32dbbc941123 frontends_multi_profiles
browser_side: fixes the contact group manager
author | souliane <souliane@mailoo.org> |
---|---|
date | Fri, 06 Feb 2015 17:53:01 +0100 |
parents | a5019e62c3e9 |
children | e0021d571eef |
comparison
equal
deleted
inserted
replaced
599:a6b9809b9a68 | 600:32dbbc941123 |
---|---|
29 import dialog | 29 import dialog |
30 import list_manager | 30 import list_manager |
31 import contact_list | 31 import contact_list |
32 | 32 |
33 | 33 |
34 unicode = str # FIXME: pyjamas workaround | |
35 | |
36 | |
34 class ContactGroupManager(list_manager.ListManager): | 37 class ContactGroupManager(list_manager.ListManager): |
35 """A manager for sub-panels to assign contacts to each group.""" | 38 |
36 | 39 def __init__(self, container, keys, contacts, offsets, style): |
37 def __init__(self, parent, keys_dict, contacts, offsets, style): | 40 """ |
38 list_manager.ListManager.__init__(self, parent, keys_dict, contacts, offsets, style) | 41 @param container (FlexTable): FlexTable parent widget |
42 @param keys (dict{unicode: dict{unicode: unicode}}): dict binding items | |
43 keys to their display config data. | |
44 @param contacts (list): list of contacts | |
45 @param offsets (dict): define widgets positions offsets within container: | |
46 - "x_first": the x offset for the first widget's row on the grid | |
47 - "x": the x offset for all widgets rows, except the first one if "x_first" is defined | |
48 - "y": the y offset for all widgets columns on the grid | |
49 @param style (dict): define CSS styles | |
50 """ | |
51 list_manager.ListManager.__init__(self, container, keys, contacts, offsets, style) | |
39 self.registerPopupMenuPanel(entries={"Remove group": {}}, | 52 self.registerPopupMenuPanel(entries={"Remove group": {}}, |
40 callback=lambda sender, key: Timer(5, lambda timer: self.removeContactKey(sender, key))) | 53 callback=lambda sender, key: Timer(5, lambda timer: self.removeContactKey(sender, key))) |
41 | 54 |
42 def removeContactKey(self, sender, key): | 55 def removeContactKey(self, sender, key): |
43 key = sender.getText() | 56 key = sender.getText() |
44 | 57 |
45 def confirm_cb(answer): | 58 def confirm_cb(answer): |
46 if answer: | 59 if answer: |
47 list_manager.ListManager.removeContactKey(self, key) | 60 list_manager.ListManager.removeItemKey(self, key) |
48 self._parent.removeKeyFromAddGroupPanel(key) | 61 self.container.removeKeyFromAddGroupPanel(key) |
49 | 62 |
50 _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to delete the group '%s'?" % key) | 63 _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to delete the group '%s'?" % key) |
51 _dialog.show() | 64 _dialog.show() |
52 | 65 |
53 def removeFromRemainingList(self, contacts): | 66 def removeFromRemainingList(self, contacts): |
54 list_manager.ListManager.removeFromRemainingList(self, contacts) | 67 list_manager.ListManager.removeFromRemainingList(self, contacts) |
55 self._parent.updateContactList(contacts=contacts) | 68 self.container.updateContactList(contacts) |
56 | 69 |
57 def addToRemainingList(self, contacts, ignore_key=None): | 70 def addToRemainingList(self, contacts, ignore_key=None): |
58 list_manager.ListManager.addToRemainingList(self, contacts, ignore_key) | 71 list_manager.ListManager.addToRemainingList(self, contacts, ignore_key) |
59 self._parent.updateContactList(contacts=contacts) | 72 self.container.updateContactList(contacts) |
60 | 73 |
61 | 74 |
62 class ContactGroupEditor(DockPanel): | 75 class ContactGroupEditor(DockPanel): |
63 """Panel for the contact groups manager.""" | 76 """A big panel including a ContactGroupManager and other UI stuff.""" |
64 | 77 |
65 def __init__(self, host, parent=None, onCloseCallback=None): | 78 def __init__(self, host, container=None, onCloseCallback=None): |
79 """ | |
80 | |
81 @param host (SatWebFrontend) | |
82 @param container (PanelBase): parent panel or None to display in a popup | |
83 @param onCloseCallback (callable) | |
84 """ | |
66 DockPanel.__init__(self) | 85 DockPanel.__init__(self) |
67 self.host = host | 86 self.host = host |
68 | 87 |
69 # eventually display in a popup | 88 # eventually display in a popup |
70 if parent is None: | 89 if container is None: |
71 parent = DialogBox(autoHide=False, centered=True) | 90 container = DialogBox(autoHide=False, centered=True) |
72 parent.setHTML("Manage contact groups") | 91 container.setHTML("Manage contact groups") |
73 self._parent = parent | 92 self.container = container |
74 self._on_close_callback = onCloseCallback | 93 self._on_close_callback = onCloseCallback |
75 self.all_contacts = self.host.contact_panel.getContacts() | 94 |
76 | 95 self.all_contacts = contact_list.JIDList(self.host.contact_list.roster_entities) |
77 groups_list = self.host.contact_panel.groups.keys() | 96 roster_entities_by_group = self.host.contact_list.roster_entities_by_group |
78 groups_list.sort() | 97 del roster_entities_by_group[None] # remove the empty group |
79 | 98 roster_groups = roster_entities_by_group.keys() |
80 self.add_group_panel = self.getAddGroupPanel(groups_list) | 99 roster_groups.sort() |
81 south_panel = self.getCloseSaveButtons() | 100 |
82 center_panel = self.getContactGroupManager(groups_list) | 101 self.add_group_panel = self.initAddGroupPanel(roster_groups) |
83 east_panel = self.getContactList() | 102 south_panel = self.initCloseSaveButtons() |
103 center_panel = self.initContactGroupManager(roster_groups) | |
104 east_panel = self.initContactList() | |
84 | 105 |
85 self.add(self.add_group_panel, DockPanel.CENTER) | 106 self.add(self.add_group_panel, DockPanel.CENTER) |
86 self.add(east_panel, DockPanel.EAST) | 107 self.add(east_panel, DockPanel.EAST) |
87 self.add(center_panel, DockPanel.NORTH) | 108 self.add(center_panel, DockPanel.NORTH) |
88 self.add(south_panel, DockPanel.SOUTH) | 109 self.add(south_panel, DockPanel.SOUTH) |
95 self.setCellHorizontalAlignment(self.add_group_panel, HasAlignment.ALIGN_LEFT) | 116 self.setCellHorizontalAlignment(self.add_group_panel, HasAlignment.ALIGN_LEFT) |
96 self.setCellVerticalAlignment(south_panel, HasAlignment.ALIGN_BOTTOM) | 117 self.setCellVerticalAlignment(south_panel, HasAlignment.ALIGN_BOTTOM) |
97 self.setCellHorizontalAlignment(south_panel, HasAlignment.ALIGN_CENTER) | 118 self.setCellHorizontalAlignment(south_panel, HasAlignment.ALIGN_CENTER) |
98 | 119 |
99 # need to be done after the contact list has been initialized | 120 # need to be done after the contact list has been initialized |
100 self.groups.setContacts(self.host.contact_panel.groups) | 121 self.groups.resetItems(roster_entities_by_group) |
101 self.toggleContacts(showAll=True) | 122 self.toggleContacts(showAll=True) |
102 | 123 |
103 # Hide the contacts list from the main panel to not confuse the user | 124 # Hide the contacts list from the main panel to not confuse the user |
104 self.restore_contact_panel = False | 125 self.restore_contact_panel = False |
105 if self.host.contact_panel.getVisible(): | 126 clist = self.host.contact_list |
127 if clist.getVisible(): | |
106 self.restore_contact_panel = True | 128 self.restore_contact_panel = True |
107 self.host.panel._contactsSwitch() | 129 self.host.panel._contactsSwitch() |
108 | 130 |
109 parent.add(self) | 131 container.add(self) |
110 parent.setVisible(True) | 132 container.setVisible(True) |
111 if isinstance(parent, DialogBox): | 133 if isinstance(container, DialogBox): |
112 parent.center() | 134 container.center() |
113 | 135 |
114 def getContactGroupManager(self, groups_list): | 136 def initContactGroupManager(self, groups): |
115 """Set the list manager for the groups""" | 137 """Initialise the contact group manager. |
116 flex_table = FlexTable(len(groups_list), 2) | 138 |
139 @param groups (list[unicode]): contact groups | |
140 """ | |
141 flex_table = FlexTable() | |
117 flex_table.addStyleName('contactGroupEditor') | 142 flex_table.addStyleName('contactGroupEditor') |
143 | |
118 # overwrite the default style which has been set for rich text editor | 144 # overwrite the default style which has been set for rich text editor |
119 style = { | 145 style = {"keyItem": "group", |
120 "keyItem": "group", | 146 "popupMenuItem": "popupMenuItem", |
121 "popupMenuItem": "popupMenuItem", | 147 "removeButton": "contactGroupRemoveButton", |
122 "removeButton": "contactGroupRemoveButton", | 148 "buttonCell": "contactGroupButtonCell", |
123 "buttonCell": "contactGroupButtonCell", | 149 "keyPanel": "contactGroupPanel" |
124 "keyPanel": "contactGroupPanel" | 150 } |
125 } | 151 |
126 self.groups = ContactGroupManager(flex_table, groups_list, self.all_contacts, style=style) | 152 groups = {group: {} for group in groups} |
127 self.groups.createWidgets() # widgets are automatically added to FlexTable | 153 self.groups = ContactGroupManager(flex_table, groups, self.all_contacts, style=style) |
154 self.groups.createWidgets() # widgets are automatically added to the FlexTable | |
155 | |
128 # FIXME: clean that part which is dangerous | 156 # FIXME: clean that part which is dangerous |
129 flex_table.updateContactList = self.updateContactList | 157 flex_table.updateContactList = self.updateContactList |
130 flex_table.removeKeyFromAddGroupPanel = self.add_group_panel.groups.remove | 158 flex_table.removeKeyFromAddGroupPanel = self.add_group_panel.groups.remove |
159 | |
131 return flex_table | 160 return flex_table |
132 | 161 |
133 def getAddGroupPanel(self, groups_list): | 162 def initAddGroupPanel(self, groups): |
134 """Add the 'Add group' panel to the FlexTable""" | 163 """Initialise the 'Add group' panel. |
135 | 164 |
136 def add_group_cb(text): | 165 @param groups (list[unicode]): contact groups |
137 self.groups.addContactKey(text) | 166 """ |
167 | |
168 def add_group_cb(key): | |
169 self.groups.addItemKey(key) | |
138 self.add_group_panel.textbox.setFocus(True) | 170 self.add_group_panel.textbox.setFocus(True) |
139 | 171 |
140 add_group_panel = dialog.AddGroupPanel(groups_list, add_group_cb) | 172 add_group_panel = dialog.AddGroupPanel(groups, add_group_cb) |
141 add_group_panel.addStyleName("addContactGroupPanel") | 173 add_group_panel.addStyleName("addContactGroupPanel") |
142 return add_group_panel | 174 return add_group_panel |
143 | 175 |
144 def getCloseSaveButtons(self): | 176 def initCloseSaveButtons(self): |
145 """Add the buttons to close the dialog / save the groups""" | 177 """Add the buttons to close the dialog and save the groups.""" |
146 buttons = HorizontalPanel() | 178 buttons = HorizontalPanel() |
147 buttons.addStyleName("marginAuto") | 179 buttons.addStyleName("marginAuto") |
148 buttons.add(Button("Save", listener=self.closeAndSave)) | 180 buttons.add(Button("Save", listener=self.closeAndSave)) |
149 buttons.add(Button("Cancel", listener=self.cancelWithoutSaving)) | 181 buttons.add(Button("Cancel", listener=self.cancelWithoutSaving)) |
150 return buttons | 182 return buttons |
151 | 183 |
152 def getContactList(self): | 184 def initContactList(self): |
153 """Add the contact list to the DockPanel""" | 185 """Add the contact list to the DockPanel.""" |
154 self.toggle = Button("", self.toggleContacts) | 186 self.toggle = Button("", self.toggleContacts) |
155 self.toggle.addStyleName("toggleAssignedContacts") | 187 self.toggle.addStyleName("toggleAssignedContacts") |
156 self.contacts = contact_list.BaseContactPanel(self.host) | 188 self.contacts = contact_list.BaseContactsPanel(self.host) |
157 for contact_ in self.all_contacts: | 189 for contact in self.all_contacts: |
158 self.contacts.add(contact_) | 190 self.contacts.add(contact) |
159 contact_panel = VerticalPanel() | 191 contact_panel = VerticalPanel() |
160 contact_panel.add(self.toggle) | 192 contact_panel.add(self.toggle) |
161 contact_panel.add(self.contacts) | 193 contact_panel.add(self.contacts) |
162 return contact_panel | 194 return contact_panel |
163 | 195 |
164 def toggleContacts(self, sender=None, showAll=None): | 196 def toggleContacts(self, sender=None, showAll=None): |
165 """Callback for the toggle button""" | 197 """Toggle the button to show contacts and the contact list. |
166 if sender is None: | 198 |
167 sender = self.toggle | 199 @param sender (Button) |
168 sender.showAll = showAll if showAll is not None else not sender.showAll | 200 @param showAll (bool): if set, initialise with True to show all contacts |
169 if sender.showAll: | 201 or with False to show only the ones that are not assigned yet. |
170 sender.setText("Hide assigned") | 202 """ |
171 else: | 203 self.toggle.showAll = (not self.toggle.showAll) if showAll is None else showAll |
172 sender.setText("Show assigned") | 204 self.toggle.setText("Hide assigned" if self.toggle.showAll else "Show assigned") |
173 self.updateContactList(sender) | 205 self.updateContactList() |
174 | 206 |
175 def updateContactList(self, sender=None, contacts=None): | 207 def updateContactList(self, contacts=None): |
176 """Update the contact list regarding the toggle button""" | 208 """Update the contact list's items visibility, depending of the toggle |
209 button and the "contacts" attribute. | |
210 | |
211 @param contacts (list): contacts to be updated, or None to update all. | |
212 """ | |
177 if not hasattr(self, "toggle") or not hasattr(self.toggle, "showAll"): | 213 if not hasattr(self, "toggle") or not hasattr(self.toggle, "showAll"): |
178 return | 214 return |
179 sender = self.toggle | |
180 if contacts is not None: | 215 if contacts is not None: |
181 if not isinstance(contacts, list): | 216 to_remove = set() |
182 contacts = [contacts] | 217 for contact in contacts: |
183 for contact_ in contacts: | 218 if contact not in self.all_contacts: |
184 if contact_ not in self.all_contacts: | 219 to_remove.add(contact) |
185 contacts.remove(contact_) | 220 for contact in to_remove: |
221 contacts.remove(contact) | |
186 else: | 222 else: |
187 contacts = self.all_contacts | 223 contacts = self.all_contacts |
188 for contact_ in contacts: | 224 for contact in contacts: |
189 if sender.showAll: | 225 if self.toggle.showAll: |
190 self.contacts.getContactBox(contact_).setVisible(True) | 226 self.contacts.getContactBox(contact).setVisible(True) |
191 else: | 227 else: |
192 if contact_ in self.groups.remaining_list: | 228 if contact in self.groups.items_remaining: |
193 self.contacts.getContactBox(contact_).setVisible(True) | 229 self.contacts.getContactBox(contact).setVisible(True) |
194 else: | 230 else: |
195 self.contacts.getContactBox(contact_).setVisible(False) | 231 self.contacts.getContactBox(contact).setVisible(False) |
196 | 232 |
197 def __close(self): | 233 def __close(self): |
198 """Remove the widget from parent or close the popup.""" | 234 """Remove the widget from parent or close the popup.""" |
199 if isinstance(self._parent, DialogBox): | 235 if isinstance(self.container, DialogBox): |
200 self._parent.hide() | 236 self.container.hide() |
201 self._parent.remove(self) | 237 self.container.remove(self) |
202 if self._on_close_callback is not None: | 238 if self._on_close_callback is not None: |
203 self._on_close_callback() | 239 self._on_close_callback() |
204 if self.restore_contact_panel: | 240 if self.restore_contact_panel: |
205 self.host.panel._contactsSwitch() | 241 self.host.panel._contactsSwitch() |
206 | 242 |
213 _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to cancel without saving?") | 249 _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to cancel without saving?") |
214 _dialog.show() | 250 _dialog.show() |
215 | 251 |
216 def closeAndSave(self): | 252 def closeAndSave(self): |
217 """Call bridge methods to save the changes and close the dialog""" | 253 """Call bridge methods to save the changes and close the dialog""" |
218 map_ = {} | 254 old_groups_by_entity = contact_list.JIDDict(self.host.contact_list.roster_groups_by_entity) |
219 for contact_ in self.all_contacts: | 255 old_entities = old_groups_by_entity.keys() |
220 map_[contact_] = set() | 256 groups_by_entity = contact_list.JIDDict(self.groups.getKeysByItem()) |
221 contacts = self.groups.getContacts() | 257 entities = groups_by_entity.keys() |
222 for group in contacts.keys(): | 258 |
223 for contact_ in contacts[group]: | 259 for invalid in entities.difference(self.all_contacts): |
224 try: | 260 dialog.InfoDialog("Invalid contact(s)", |
225 map_[contact_].add(group) | 261 "The contact '%s' is not in your contact list but has been assigned to: '%s'." % (invalid, "', '".join(groups_by_entity[invalid])) + |
226 except KeyError: | 262 "Your changes could not be saved: please check your assignments and save again.", Width="400px").center() |
227 dialog.InfoDialog("Invalid contact", | 263 return |
228 "The contact '%s' is not your contact list but it has been assigned to the group '%s'." % (contact_, group) + | 264 |
229 "Your changes could not be saved: please check your assignments and save again.", Width="400px").center() | 265 for entity in old_entities.difference(entities): |
230 return | 266 self.host.bridge.call('updateContact', None, unicode(entity), '', []) |
231 for contact_ in map_.keys(): | 267 |
232 groups = map_[contact_] | 268 for entity, groups in groups_by_entity.iteritems(): |
233 current_groups = self.host.contact_panel.getContactGroups(contact_) | 269 if entity not in old_groups_by_entity or groups != old_groups_by_entity[entity]: |
234 if groups != current_groups: | 270 self.host.bridge.call('updateContact', None, unicode(entity), '', list(groups)) |
235 self.host.bridge.call('updateContact', None, contact_, '', list(groups)) | |
236 self.__close() | 271 self.__close() |