Mercurial > libervia-web
diff browser_side/contact_group.py @ 263:d3c734669577
browser_side: improvements for lists and contact groups manager:
- use DockPanel to deal with UI problems
- fixed issues with the autocomplete list
- avoid duplicate contacts in a contact list
- signal invalid contacts with a red border
- check for invalid contacts in the form before saving
- better genericity for the class DragAutoCompleteTextBox
author | souliane <souliane@mailoo.org> |
---|---|
date | Mon, 11 Nov 2013 12:48:33 +0100 |
parents | 0e7f3944bd27 |
children | 2067d6241927 |
line wrap: on
line diff
--- a/browser_side/contact_group.py Mon Nov 11 10:44:44 2013 +0100 +++ b/browser_side/contact_group.py Mon Nov 11 12:48:33 2013 +0100 @@ -20,15 +20,17 @@ """ from pyjamas.ui.FlexTable import FlexTable -from browser_side.dialog import ConfirmDialog -from list_manager import ListManager -import contact +from pyjamas.ui.DockPanel import DockPanel from pyjamas.Timer import Timer from pyjamas.ui.Button import Button from pyjamas.ui.HorizontalPanel import HorizontalPanel from pyjamas.ui.VerticalPanel import VerticalPanel from pyjamas.ui.DialogBox import DialogBox +from pyjamas.ui import HasAlignment +from browser_side.dialog import ConfirmDialog, InfoDialog +from list_manager import ListManager import dialog +import contact class ContactGroupManager(ListManager): @@ -44,52 +46,77 @@ def confirm_cb(answer): if answer: - (y, x) = self._parent.getIndex(self.__children[key]["button"]) - self._parent.removeCell(y, x + 1) - self._parent.removeCell(y, x) - del self.__keys_dict[key] - del self.__children[key] - self._parent.add_group_panel.groups.remove(key) + ListManager.removeContactKey(self, key) + self._parent.removeKeyFromAddGroupPanel(key) _dialog = ConfirmDialog(confirm_cb, text="Do you really want to delete the group '%s'?" % key) _dialog.show() - def removeFromRemainingList(self, contact_): - ListManager.removeFromRemainingList(self, contact_) - self._parent.updateContactList(contact_=contact_) + def removeFromRemainingList(self, contacts): + ListManager.removeFromRemainingList(self, contacts) + self._parent.updateContactList(contacts=contacts) - def addToRemainingList(self, contact_): - ListManager.addToRemainingList(self, contact_) - self._parent.updateContactList(contact_=contact_) + def addToRemainingList(self, contacts, ignore_key=None): + ListManager.addToRemainingList(self, contacts, ignore_key) + self._parent.updateContactList(contacts=contacts) -class ContactGroupEditor(FlexTable): +class ContactGroupEditor(DockPanel): """Panel for the contact groups manager.""" def __init__(self, host, parent=None, onCloseCallback=None): - # This must be done before FlexTable.__init__ because it is used by setVisible + DockPanel.__init__(self) self.host = host + + # eventually display in a popup if parent is None: parent = DialogBox(autoHide=False, centered=True) parent.setHTML("Manage contact groups") - self._parent = parent self._on_close_callback = onCloseCallback + self.all_contacts = self.host.contact_panel.getContacts() groups_list = self.host.contact_panel.groups.keys() groups_list.sort() - FlexTable.__init__(self, len(groups_list) + 2, 3) - self.addStyleName('contactGroupEditor') + + self.add_group_panel = self.getAddGroupPanel(groups_list) + south_panel = self.getCloseSaveButtons() + center_panel = self.getContactGroupManager(groups_list) + east_panel = self.getContactList() + + self.add(self.add_group_panel, DockPanel.CENTER) + self.add(east_panel, DockPanel.EAST) + self.add(center_panel, DockPanel.NORTH) + self.add(south_panel, DockPanel.SOUTH) + + self.setCellHorizontalAlignment(center_panel, HasAlignment.ALIGN_LEFT) + self.setCellVerticalAlignment(center_panel, HasAlignment.ALIGN_TOP) + self.setCellHorizontalAlignment(east_panel, HasAlignment.ALIGN_RIGHT) + self.setCellVerticalAlignment(east_panel, HasAlignment.ALIGN_TOP) + self.setCellVerticalAlignment(self.add_group_panel, HasAlignment.ALIGN_BOTTOM) + self.setCellHorizontalAlignment(self.add_group_panel, HasAlignment.ALIGN_LEFT) + self.setCellVerticalAlignment(south_panel, HasAlignment.ALIGN_BOTTOM) + self.setCellHorizontalAlignment(south_panel, HasAlignment.ALIGN_CENTER) - def cb(text): - nb_keys = len(self.groups.keys) - self.getFlexCellFormatter().setColSpan(nb_keys + 1, 0, 1) - self.getFlexCellFormatter().setColSpan(nb_keys + 2, 0, 1) - self.remove(self.add_group_panel) - self.remove(self.command) - self.groups.addContactKey(text) - refresh() + # need to be done after the contact list has been initialized + self.groups.setContacts(self.host.contact_panel.groups) + self.toggleContacts(showAll=True) + + # Hide the contacts list from the main panel to not confuse the user + self.restore_contact_panel = False + if self.host.contact_panel.getVisible(): + self.restore_contact_panel = True + self.host.panel._contactsSwitch() + parent.add(self) + parent.setVisible(True) + if isinstance(parent, DialogBox): + parent.center() + + def getContactGroupManager(self, groups_list): + """Set the list manager for the groups""" + flex_table = FlexTable(len(groups_list), 2) + flex_table.addStyleName('contactGroupEditor') # overwrite the default style which has been set for rich text editor style = { "keyItem": "group", @@ -98,81 +125,76 @@ "buttonCell": "contactGroupButtonCell", "keyPanel": "contactGroupPanel" } - self.all_contacts = self.host.contact_panel.getContacts() - self.groups = ContactGroupManager(self, groups_list, self.all_contacts, style=style) - self.groups.createWidgets() - - self.add_group_panel = dialog.AddGroupPanel(groups_list, cb) - self.add_group_panel.addStyleName("addContactGroupPanel") - - self.command = HorizontalPanel() - self.command.addStyleName("marginAuto") - self.command.add(Button("Cancel", listener=self.cancelWithoutSaving)) - self.command.add(Button("Save", listener=self.closeAndSave)) + self.groups = ContactGroupManager(flex_table, groups_list, self.all_contacts, style=style) + self.groups.createWidgets() # widgets are automatically added to FlexTable + # FIXME: clean that part which is dangerous + flex_table.updateContactList = self.updateContactList + flex_table.removeKeyFromAddGroupPanel = self.add_group_panel.groups.remove + return flex_table - contact_panel = VerticalPanel() + def getAddGroupPanel(self, groups_list): + """Add the 'Add group' panel to the FlexTable""" - # checkbox has been replaced by a button - self.checkbox = Button("", self.toggleContacts) - self.checkbox.getChecked = lambda: self.checkbox.checked if hasattr(self.checkbox, "checked") else None - self.checkbox.addStyleName("toggleAssignedContacts") - contact_panel.add(self.checkbox) - self.contacts = contact.GenericContactList(host) - contact_panel.add(self.contacts) - for contact in self.all_contacts: - self.contacts.add(contact) - self.setWidget(0, 2, contact_panel) + def add_group_cb(text): + self.groups.addContactKey(text) + self.add_group_panel.textbox.setFocus(True) + + add_group_panel = dialog.AddGroupPanel(groups_list, add_group_cb) + add_group_panel.addStyleName("addContactGroupPanel") + return add_group_panel - def refresh(): - nb_keys = len(self.groups.keys) - self.getFlexCellFormatter().setColSpan(nb_keys + 1, 0, 2) # add group panel - self.setWidget(nb_keys + 1, 0, self.add_group_panel) - self.getFlexCellFormatter().setColSpan(nb_keys + 2, 0, 3) # buttons panel - self.setWidget(nb_keys + 2, 0, self.command) - self.getFlexCellFormatter().setRowSpan(0, 2, nb_keys + 2) # contact list + def getCloseSaveButtons(self): + """Add the buttons to close the dialog / save the groups""" + buttons = HorizontalPanel() + buttons.addStyleName("marginAuto") + buttons.add(Button("Cancel", listener=self.cancelWithoutSaving)) + buttons.add(Button("Save", listener=self.closeAndSave)) + return buttons - self.groups.setContacts(self.host.contact_panel.groups) - refresh() - self.restore_contact_panel = False - if self.host.contact_panel.getVisible(): - self.restore_contact_panel = True - self.host.panel._contactsSwitch() - self.toggleContacts() - parent.add(self) - parent.setVisible(True) - if isinstance(parent, DialogBox): - parent.center() + def getContactList(self): + """Add the contact list to the DockPanel""" + self.toggle = Button("", self.toggleContacts) + self.toggle.addStyleName("toggleAssignedContacts") + self.contacts = contact.GenericContactList(self.host) + for contact_ in self.all_contacts: + self.contacts.add(contact_) + contact_panel = VerticalPanel() + contact_panel.add(self.toggle) + contact_panel.add(self.contacts) + return contact_panel - def toggleContacts(self, sender=None): + def toggleContacts(self, sender=None, showAll=None): + """Callback for the toggle button""" if sender is None: - sender = self.checkbox - if sender.getChecked(): - sender.checked = False + sender = self.toggle + sender.showAll = showAll if showAll is not None else not sender.showAll + if sender.showAll: sender.setText("Hide assigned") else: - sender.checked = True sender.setText("Show assigned") self.updateContactList(sender) - def updateContactList(self, sender=None, contact_=None): - sender = self.checkbox - if sender.getChecked() is None: - # do not update during initialization + def updateContactList(self, sender=None, contacts=None): + """Update the contact list regarding the toggle button""" + if not hasattr(self, "toggle") or not hasattr(self.toggle, "showAll"): return - if contact_ is not None: - if contact_ not in self.all_contacts or not sender.getChecked(): - return - all_contacts = [contact_] + sender = self.toggle + if contacts is not None: + if not isinstance(contacts, list): + contacts = [contacts] + for contact_ in contacts: + if contact_ not in self.all_contacts: + contacts.remove(contact_) else: - all_contacts = self.all_contacts - for contact_ in all_contacts: - if sender.getChecked(): + contacts = self.all_contacts + for contact_ in contacts: + if sender.showAll: + self.contacts.getContactLabel(contact_).setVisible(True) + else: if contact_ in self.groups.remaining_list: self.contacts.getContactLabel(contact_).setVisible(True) else: self.contacts.getContactLabel(contact_).setVisible(False) - else: - self.contacts.getContactLabel(contact_).setVisible(True) def __close(self): """Remove the widget from parent or close the popup.""" @@ -194,13 +216,20 @@ _dialog.show() def closeAndSave(self): + """Call bridge methods to save the changes and close the dialog""" map_ = {} for contact_ in self.all_contacts: map_[contact_] = set() contacts = self.groups.getContacts() for group in contacts.keys(): for contact_ in contacts[group]: - map_[contact_].add(group) + try: + map_[contact_].add(group) + except KeyError: + InfoDialog("Invalid contact", + "The contact '%s' is not your contact list but it has been assigned to the group '%s'." % (contact_, group) + + "Your changes could not be saved: please check your assignments and save again.", Width="400px").center() + return for contact_ in map_.keys(): groups = map_[contact_] current_groups = self.host.contact_panel.getContactGroups(contact_)