comparison src/browser/contact_group.py @ 449:981ed669d3b3

/!\ reorganize all the file hierarchy, move the code and launching script to src: - browser_side --> src/browser - public --> src/browser_side/public - libervia.py --> src/browser/libervia_main.py - libervia_server --> src/server - libervia_server/libervia.sh --> src/libervia.sh - twisted --> src/twisted - new module src/common - split constants.py in 3 files: - src/common/constants.py - src/browser/constants.py - src/server/constants.py - output --> html (generated by pyjsbuild during the installation) - new option/parameter "data_dir" (-d) to indicates the directory containing html and server_css - setup.py installs libervia to the following paths: - src/common --> <LIB>/libervia/common - src/server --> <LIB>/libervia/server - src/twisted --> <LIB>/twisted - html --> <SHARE>/libervia/html - server_side --> <SHARE>libervia/server_side - LIBERVIA_INSTALL environment variable takes 2 new options with prompt confirmation: - clean: remove previous installation directories - purge: remove building and previous installation directories You may need to update your sat.conf and/or launching script to update the following options/parameters: - ssl_certificate - data_dir
author souliane <souliane@mailoo.org>
date Tue, 20 May 2014 06:41:16 +0200
parents browser_side/contact_group.py@8ecc5a7062e4
children
comparison
equal deleted inserted replaced
448:14c35f7f1ef5 449:981ed669d3b3
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 # Libervia: a Salut à Toi frontend
5 # Copyright (C) 2013, 2014 Adrien Cossa <souliane@mailoo.org>
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 from pyjamas.ui.FlexTable import FlexTable
21 from pyjamas.ui.DockPanel import DockPanel
22 from pyjamas.Timer import Timer
23 from pyjamas.ui.Button import Button
24 from pyjamas.ui.HorizontalPanel import HorizontalPanel
25 from pyjamas.ui.VerticalPanel import VerticalPanel
26 from pyjamas.ui.DialogBox import DialogBox
27 from pyjamas.ui import HasAlignment
28
29 from dialog import ConfirmDialog, InfoDialog
30 from list_manager import ListManager
31 import dialog
32 import contact
33
34
35 class ContactGroupManager(ListManager):
36 """A manager for sub-panels to assign contacts to each group."""
37
38 def __init__(self, parent, keys_dict, contact_list, offsets, style):
39 ListManager.__init__(self, parent, keys_dict, contact_list, offsets, style)
40 self.registerPopupMenuPanel(entries={"Remove group": {}},
41 callback=lambda sender, key: Timer(5, lambda timer: self.removeContactKey(sender, key)))
42
43 def removeContactKey(self, sender, key):
44 key = sender.getText()
45
46 def confirm_cb(answer):
47 if answer:
48 ListManager.removeContactKey(self, key)
49 self._parent.removeKeyFromAddGroupPanel(key)
50
51 _dialog = ConfirmDialog(confirm_cb, text="Do you really want to delete the group '%s'?" % key)
52 _dialog.show()
53
54 def removeFromRemainingList(self, contacts):
55 ListManager.removeFromRemainingList(self, contacts)
56 self._parent.updateContactList(contacts=contacts)
57
58 def addToRemainingList(self, contacts, ignore_key=None):
59 ListManager.addToRemainingList(self, contacts, ignore_key)
60 self._parent.updateContactList(contacts=contacts)
61
62
63 class ContactGroupEditor(DockPanel):
64 """Panel for the contact groups manager."""
65
66 def __init__(self, host, parent=None, onCloseCallback=None):
67 DockPanel.__init__(self)
68 self.host = host
69
70 # eventually display in a popup
71 if parent is None:
72 parent = DialogBox(autoHide=False, centered=True)
73 parent.setHTML("Manage contact groups")
74 self._parent = parent
75 self._on_close_callback = onCloseCallback
76 self.all_contacts = self.host.contact_panel.getContacts()
77
78 groups_list = self.host.contact_panel.groups.keys()
79 groups_list.sort()
80
81 self.add_group_panel = self.getAddGroupPanel(groups_list)
82 south_panel = self.getCloseSaveButtons()
83 center_panel = self.getContactGroupManager(groups_list)
84 east_panel = self.getContactList()
85
86 self.add(self.add_group_panel, DockPanel.CENTER)
87 self.add(east_panel, DockPanel.EAST)
88 self.add(center_panel, DockPanel.NORTH)
89 self.add(south_panel, DockPanel.SOUTH)
90
91 self.setCellHorizontalAlignment(center_panel, HasAlignment.ALIGN_LEFT)
92 self.setCellVerticalAlignment(center_panel, HasAlignment.ALIGN_TOP)
93 self.setCellHorizontalAlignment(east_panel, HasAlignment.ALIGN_RIGHT)
94 self.setCellVerticalAlignment(east_panel, HasAlignment.ALIGN_TOP)
95 self.setCellVerticalAlignment(self.add_group_panel, HasAlignment.ALIGN_BOTTOM)
96 self.setCellHorizontalAlignment(self.add_group_panel, HasAlignment.ALIGN_LEFT)
97 self.setCellVerticalAlignment(south_panel, HasAlignment.ALIGN_BOTTOM)
98 self.setCellHorizontalAlignment(south_panel, HasAlignment.ALIGN_CENTER)
99
100 # need to be done after the contact list has been initialized
101 self.groups.setContacts(self.host.contact_panel.groups)
102 self.toggleContacts(showAll=True)
103
104 # Hide the contacts list from the main panel to not confuse the user
105 self.restore_contact_panel = False
106 if self.host.contact_panel.getVisible():
107 self.restore_contact_panel = True
108 self.host.panel._contactsSwitch()
109
110 parent.add(self)
111 parent.setVisible(True)
112 if isinstance(parent, DialogBox):
113 parent.center()
114
115 def getContactGroupManager(self, groups_list):
116 """Set the list manager for the groups"""
117 flex_table = FlexTable(len(groups_list), 2)
118 flex_table.addStyleName('contactGroupEditor')
119 # overwrite the default style which has been set for rich text editor
120 style = {
121 "keyItem": "group",
122 "popupMenuItem": "popupMenuItem",
123 "removeButton": "contactGroupRemoveButton",
124 "buttonCell": "contactGroupButtonCell",
125 "keyPanel": "contactGroupPanel"
126 }
127 self.groups = ContactGroupManager(flex_table, groups_list, self.all_contacts, style=style)
128 self.groups.createWidgets() # widgets are automatically added to FlexTable
129 # FIXME: clean that part which is dangerous
130 flex_table.updateContactList = self.updateContactList
131 flex_table.removeKeyFromAddGroupPanel = self.add_group_panel.groups.remove
132 return flex_table
133
134 def getAddGroupPanel(self, groups_list):
135 """Add the 'Add group' panel to the FlexTable"""
136
137 def add_group_cb(text):
138 self.groups.addContactKey(text)
139 self.add_group_panel.textbox.setFocus(True)
140
141 add_group_panel = dialog.AddGroupPanel(groups_list, add_group_cb)
142 add_group_panel.addStyleName("addContactGroupPanel")
143 return add_group_panel
144
145 def getCloseSaveButtons(self):
146 """Add the buttons to close the dialog / save the groups"""
147 buttons = HorizontalPanel()
148 buttons.addStyleName("marginAuto")
149 buttons.add(Button("Save", listener=self.closeAndSave))
150 buttons.add(Button("Cancel", listener=self.cancelWithoutSaving))
151 return buttons
152
153 def getContactList(self):
154 """Add the contact list to the DockPanel"""
155 self.toggle = Button("", self.toggleContacts)
156 self.toggle.addStyleName("toggleAssignedContacts")
157 self.contacts = contact.GenericContactList(self.host)
158 for contact_ in self.all_contacts:
159 self.contacts.add(contact_)
160 contact_panel = VerticalPanel()
161 contact_panel.add(self.toggle)
162 contact_panel.add(self.contacts)
163 return contact_panel
164
165 def toggleContacts(self, sender=None, showAll=None):
166 """Callback for the toggle button"""
167 if sender is None:
168 sender = self.toggle
169 sender.showAll = showAll if showAll is not None else not sender.showAll
170 if sender.showAll:
171 sender.setText("Hide assigned")
172 else:
173 sender.setText("Show assigned")
174 self.updateContactList(sender)
175
176 def updateContactList(self, sender=None, contacts=None):
177 """Update the contact list regarding the toggle button"""
178 if not hasattr(self, "toggle") or not hasattr(self.toggle, "showAll"):
179 return
180 sender = self.toggle
181 if contacts is not None:
182 if not isinstance(contacts, list):
183 contacts = [contacts]
184 for contact_ in contacts:
185 if contact_ not in self.all_contacts:
186 contacts.remove(contact_)
187 else:
188 contacts = self.all_contacts
189 for contact_ in contacts:
190 if sender.showAll:
191 self.contacts.getContactLabel(contact_).setVisible(True)
192 else:
193 if contact_ in self.groups.remaining_list:
194 self.contacts.getContactLabel(contact_).setVisible(True)
195 else:
196 self.contacts.getContactLabel(contact_).setVisible(False)
197
198 def __close(self):
199 """Remove the widget from parent or close the popup."""
200 if isinstance(self._parent, DialogBox):
201 self._parent.hide()
202 self._parent.remove(self)
203 if self._on_close_callback is not None:
204 self._on_close_callback()
205 if self.restore_contact_panel:
206 self.host.panel._contactsSwitch()
207
208 def cancelWithoutSaving(self):
209 """Ask for confirmation before closing the dialog."""
210 def confirm_cb(answer):
211 if answer:
212 self.__close()
213
214 _dialog = ConfirmDialog(confirm_cb, text="Do you really want to cancel without saving?")
215 _dialog.show()
216
217 def closeAndSave(self):
218 """Call bridge methods to save the changes and close the dialog"""
219 map_ = {}
220 for contact_ in self.all_contacts:
221 map_[contact_] = set()
222 contacts = self.groups.getContacts()
223 for group in contacts.keys():
224 for contact_ in contacts[group]:
225 try:
226 map_[contact_].add(group)
227 except KeyError:
228 InfoDialog("Invalid contact",
229 "The contact '%s' is not your contact list but it has been assigned to the group '%s'." % (contact_, group) +
230 "Your changes could not be saved: please check your assignments and save again.", Width="400px").center()
231 return
232 for contact_ in map_.keys():
233 groups = map_[contact_]
234 current_groups = self.host.contact_panel.getContactGroups(contact_)
235 if groups != current_groups:
236 self.host.bridge.call('updateContact', None, contact_, '', list(groups))
237 self.__close()