Mercurial > libervia-web
diff src/browser/sat_browser/contact_group.py @ 467:97c72fe4a5f2
browser_side: import fixes:
- moved browser modules in a sat_browser packages, to avoid import conflicts with std lib (e.g. logging), and let pyjsbuild work normaly
- refactored bad import practices: classes are most of time not imported directly, module is imported instead.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 09 Jun 2014 22:15:26 +0200 |
parents | src/browser/contact_group.py@981ed669d3b3 |
children | 50b286866739 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/browser/sat_browser/contact_group.py Mon Jun 09 22:15:26 2014 +0200 @@ -0,0 +1,236 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Libervia: a Salut à Toi frontend +# Copyright (C) 2013, 2014 Adrien Cossa <souliane@mailoo.org> + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from pyjamas.ui.FlexTable import FlexTable +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 + +import dialog +import list_manager +import contact + + +class ContactGroupManager(list_manager.ListManager): + """A manager for sub-panels to assign contacts to each group.""" + + def __init__(self, parent, keys_dict, contact_list, offsets, style): + list_manager.ListManager.__init__(self, parent, keys_dict, contact_list, offsets, style) + self.registerPopupMenuPanel(entries={"Remove group": {}}, + callback=lambda sender, key: Timer(5, lambda timer: self.removeContactKey(sender, key))) + + def removeContactKey(self, sender, key): + key = sender.getText() + + def confirm_cb(answer): + if answer: + list_manager.ListManager.removeContactKey(self, key) + self._parent.removeKeyFromAddGroupPanel(key) + + _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to delete the group '%s'?" % key) + _dialog.show() + + def removeFromRemainingList(self, contacts): + list_manager.ListManager.removeFromRemainingList(self, contacts) + self._parent.updateContactList(contacts=contacts) + + def addToRemainingList(self, contacts, ignore_key=None): + list_manager.ListManager.addToRemainingList(self, contacts, ignore_key) + self._parent.updateContactList(contacts=contacts) + + +class ContactGroupEditor(DockPanel): + """Panel for the contact groups manager.""" + + def __init__(self, host, parent=None, onCloseCallback=None): + 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() + + 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) + + # 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", + "popupMenuItem": "popupMenuItem", + "removeButton": "contactGroupRemoveButton", + "buttonCell": "contactGroupButtonCell", + "keyPanel": "contactGroupPanel" + } + 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 + + def getAddGroupPanel(self, groups_list): + """Add the 'Add group' panel to the FlexTable""" + + 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 getCloseSaveButtons(self): + """Add the buttons to close the dialog / save the groups""" + buttons = HorizontalPanel() + buttons.addStyleName("marginAuto") + buttons.add(Button("Save", listener=self.closeAndSave)) + buttons.add(Button("Cancel", listener=self.cancelWithoutSaving)) + return buttons + + 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, showAll=None): + """Callback for the toggle button""" + if sender is None: + sender = self.toggle + sender.showAll = showAll if showAll is not None else not sender.showAll + if sender.showAll: + sender.setText("Hide assigned") + else: + sender.setText("Show assigned") + self.updateContactList(sender) + + 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 + 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: + 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) + + def __close(self): + """Remove the widget from parent or close the popup.""" + if isinstance(self._parent, DialogBox): + self._parent.hide() + self._parent.remove(self) + if self._on_close_callback is not None: + self._on_close_callback() + if self.restore_contact_panel: + self.host.panel._contactsSwitch() + + def cancelWithoutSaving(self): + """Ask for confirmation before closing the dialog.""" + def confirm_cb(answer): + if answer: + self.__close() + + _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to cancel without saving?") + _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]: + try: + map_[contact_].add(group) + except KeyError: + dialog.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_) + if groups != current_groups: + self.host.bridge.call('updateContact', None, contact_, '', list(groups)) + self.__close()