view browser_side/contact_group.py @ 256:0e7f3944bd27

browser_side: added contact group manager based on ListManager
author souliane <souliane@mailoo.org>
date Sat, 09 Nov 2013 09:39:45 +0100
parents
children d3c734669577
line wrap: on
line source

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Libervia: a Salut à Toi frontend
Copyright (C) 2013 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 browser_side.dialog import ConfirmDialog
from list_manager import ListManager
import contact
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
import dialog


class ContactGroupManager(ListManager):
    """A manager for sub-panels to assign contacts to each group."""

    def __init__(self, parent, keys_dict, contact_list, offsets, style):
        ListManager.__init__(self, parent, keys_dict, contact_list, offsets, style)
        self.registerPopupMenuPanel(entries={"Remove group": {}},
                                    callback=lambda sender, key: Timer(5, lambda: self.removeContactKey(sender, key)))

    def removeContactKey(self, sender, key):
        key = sender.getText()

        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)

        _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 addToRemainingList(self, contact_):
        ListManager.addToRemainingList(self, contact_)
        self._parent.updateContactList(contact_=contact_)


class ContactGroupEditor(FlexTable):
    """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
        self.host = host
        if parent is None:
            parent = DialogBox(autoHide=False, centered=True)
            parent.setHTML("Manage contact groups")

        self._parent = parent
        self._on_close_callback = onCloseCallback

        groups_list = self.host.contact_panel.groups.keys()
        groups_list.sort()
        FlexTable.__init__(self, len(groups_list) + 2, 3)
        self.addStyleName('contactGroupEditor')

        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()

        # overwrite the default style which has been set for rich text editor
        style = {
           "keyItem": "group",
           "popupMenuItem": "popupMenuItem",
           "removeButton": "contactGroupRemoveButton",
           "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))

        contact_panel = VerticalPanel()

        # 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 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

        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 toggleContacts(self, sender=None):
        if sender is None:
            sender = self.checkbox
        if sender.getChecked():
            sender.checked = False
            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
            return
        if contact_ is not None:
            if contact_ not in self.all_contacts or not sender.getChecked():
                return
            all_contacts = [contact_]
        else:
            all_contacts = self.all_contacts
        for contact_ in all_contacts:
            if sender.getChecked():
                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."""
        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 = ConfirmDialog(confirm_cb, text="Do you really want to cancel without saving?")
        _dialog.show()

    def closeAndSave(self):
        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)
        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()