Mercurial > libervia-web
comparison src/browser/sat_browser/menu.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/menu.py@bea9788f3170 |
children | a7f5448a1bc3 |
comparison
equal
deleted
inserted
replaced
466:01880aa8ea2d | 467:97c72fe4a5f2 |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Libervia: a Salut à Toi frontend | |
5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.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 import pyjd # this is dummy in pyjs | |
21 from sat.core.log import getLogger | |
22 log = getLogger(__name__) | |
23 | |
24 from sat.core.i18n import _ | |
25 | |
26 from pyjamas.ui.SimplePanel import SimplePanel | |
27 from pyjamas.ui.MenuBar import MenuBar | |
28 from pyjamas.ui.MenuItem import MenuItem | |
29 from pyjamas.ui.HTML import HTML | |
30 from pyjamas.ui.Frame import Frame | |
31 from pyjamas import Window | |
32 | |
33 import jid | |
34 | |
35 import file_tools | |
36 import xmlui | |
37 import panels | |
38 import dialog | |
39 import contact_group | |
40 | |
41 | |
42 class MenuCmd: | |
43 | |
44 def __init__(self, object_, handler): | |
45 self._object = object_ | |
46 self._handler = handler | |
47 | |
48 def execute(self): | |
49 handler = getattr(self._object, self._handler) | |
50 handler() | |
51 | |
52 | |
53 class PluginMenuCmd: | |
54 | |
55 def __init__(self, host, action_id): | |
56 self.host = host | |
57 self.action_id = action_id | |
58 | |
59 def execute(self): | |
60 self.host.launchAction(self.action_id, None) | |
61 | |
62 | |
63 class LiberviaMenuBar(MenuBar): | |
64 | |
65 def __init__(self): | |
66 MenuBar.__init__(self, vertical=False) | |
67 self.setStyleName('gwt-MenuBar-horizontal') # XXX: workaround for the Pyjamas' class name fix (it's now "gwt-MenuBar gwt-MenuBar-horizontal") | |
68 # TODO: properly adapt CSS to the new class name | |
69 | |
70 def doItemAction(self, item, fireCommand): | |
71 MenuBar.doItemAction(self, item, fireCommand) | |
72 if item == self.items[-1] and self.popup: | |
73 self.popup.setPopupPosition(Window.getClientWidth() - | |
74 self.popup.getOffsetWidth() - 22, | |
75 self.getAbsoluteTop() + | |
76 self.getOffsetHeight() - 1) | |
77 self.popup.addStyleName('menuLastPopup') | |
78 | |
79 | |
80 class AvatarUpload(file_tools.FileUploadPanel): | |
81 def __init__(self): | |
82 texts = {'ok_button': 'Upload avatar', | |
83 'body': 'Please select an image to show as your avatar...<br>Your picture must be a square and will be resized to 64x64 pixels if necessary.', | |
84 'errback': "Can't open image... did you actually submit an image?", | |
85 'body_errback': 'Please select another image file.', | |
86 'callback': "Your new profile picture has been set!"} | |
87 file_tools.FileUploadPanel.__init__(self, 'upload_avatar', 'avatar_path', 2, texts) | |
88 | |
89 | |
90 class Menu(SimplePanel): | |
91 | |
92 def __init__(self, host): | |
93 self.host = host | |
94 SimplePanel.__init__(self) | |
95 self.setStyleName('menuContainer') | |
96 | |
97 def createMenus(self, add_menus): | |
98 _item_tpl = "<img src='media/icons/menu/%s_menu_red.png' />%s" | |
99 menus_dict = {} | |
100 menus_order = [] | |
101 | |
102 def addMenu(menu_name, menu_name_i18n, item_name_i18n, icon, menu_cmd): | |
103 """ add a menu to menu_dict """ | |
104 log.info("addMenu: %s %s %s %s %s" % (menu_name, menu_name_i18n, item_name_i18n, icon, menu_cmd)) | |
105 try: | |
106 menu_bar = menus_dict[menu_name] | |
107 except KeyError: | |
108 menu_bar = menus_dict[menu_name] = MenuBar(vertical=True) | |
109 menus_order.append((menu_name, menu_name_i18n, icon)) | |
110 if item_name_i18n and menu_cmd: | |
111 menu_bar.addItem(item_name_i18n, menu_cmd) | |
112 | |
113 addMenu("General", _("General"), _("Web widget"), 'home', MenuCmd(self, "onWebWidget")) | |
114 addMenu("General", _("General"), _("Disconnect"), 'home', MenuCmd(self, "onDisconnect")) | |
115 addMenu("Contacts", _("Contacts"), None, 'social', None) | |
116 addMenu("Groups", _("Groups"), _("Discussion"), 'social', MenuCmd(self, "onJoinRoom")) | |
117 addMenu("Groups", _("Groups"), _("Collective radio"), 'social', MenuCmd(self, "onCollectiveRadio")) | |
118 addMenu("Games", _("Games"), _("Tarot"), 'games', MenuCmd(self, "onTarotGame")) | |
119 addMenu("Games", _("Games"), _("Xiangqi"), 'games', MenuCmd(self, "onXiangqiGame")) | |
120 | |
121 # additional menus | |
122 for action_id, type_, path, path_i18n in add_menus: | |
123 if not path: | |
124 log.warning("skipping menu without path") | |
125 continue | |
126 if len(path) != len(path_i18n): | |
127 log.error("inconsistency between menu paths") | |
128 continue | |
129 menu_name = path[0] | |
130 menu_name_i18n = path_i18n[0] | |
131 item_name = path[1:] | |
132 if not item_name: | |
133 log.warning("skipping menu with a path of lenght 1 [%s]" % path[0]) | |
134 continue | |
135 item_name_i18n = ' | '.join(path_i18n[1:]) | |
136 addMenu(menu_name, menu_name_i18n, item_name_i18n, 'plugins', PluginMenuCmd(self.host, action_id)) | |
137 | |
138 # menu items that should be displayed after the automatically added ones | |
139 addMenu("Contacts", _("Contacts"), _("Manage groups"), 'social', MenuCmd(self, "onManageContactGroups")) | |
140 | |
141 menus_order.append(None) # we add separator | |
142 | |
143 addMenu("Help", _("Help"), _("Social contract"), 'help', MenuCmd(self, "onSocialContract")) | |
144 addMenu("Help", _("Help"), _("About"), 'help', MenuCmd(self, "onAbout")) | |
145 addMenu("Settings", _("Settings"), _("Account"), 'settings', MenuCmd(self, "onAccount")) | |
146 addMenu("Settings", _("Settings"), _("Parameters"), 'settings', MenuCmd(self, "onParameters")) | |
147 | |
148 # XXX: temporary, will change when a full profile will be managed in SàT | |
149 addMenu("Settings", _("Settings"), _("Upload avatar"), 'settings', MenuCmd(self, "onAvatarUpload")) | |
150 | |
151 menubar = LiberviaMenuBar() | |
152 | |
153 for menu_data in menus_order: | |
154 if menu_data is None: | |
155 _separator = MenuItem('', None) | |
156 _separator.setStyleName('menuSeparator') | |
157 menubar.addItem(_separator, None) | |
158 else: | |
159 menu_name, menu_name_i18n, icon = menu_data | |
160 menubar.addItem(MenuItem(_item_tpl % (icon, menu_name_i18n), True, menus_dict[menu_name])) | |
161 | |
162 self.add(menubar) | |
163 | |
164 #General menu | |
165 def onWebWidget(self): | |
166 web_panel = panels.WebPanel(self.host, "http://www.goffi.org") | |
167 self.host.addWidget(web_panel) | |
168 self.host.setSelected(web_panel) | |
169 | |
170 def onDisconnect(self): | |
171 def confirm_cb(answer): | |
172 if answer: | |
173 log.info("disconnection") | |
174 self.host.bridge.call('disconnect', None) | |
175 _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to disconnect ?") | |
176 _dialog.show() | |
177 | |
178 def onSocialContract(self): | |
179 _frame = Frame('contrat_social.html') | |
180 _frame.setStyleName('infoFrame') | |
181 _dialog = dialog.GenericDialog("Contrat Social", _frame) | |
182 _dialog.setSize('80%', '80%') | |
183 _dialog.show() | |
184 | |
185 def onAbout(self): | |
186 _about = HTML("""<b>Libervia</b>, a Salut à Toi project<br /> | |
187 <br /> | |
188 You can contact the author at <a href="mailto:goffi@goffi.org">goffi@goffi.org</a><br /> | |
189 Blog available (mainly in french) at <a href="http://www.goffi.org" target="_blank">http://www.goffi.org</a><br /> | |
190 Project page: <a href="http://sat.goffi.org"target="_blank">http://sat.goffi.org</a><br /> | |
191 <br /> | |
192 Any help welcome :) | |
193 <p style='font-size:small;text-align:center'>This project is dedicated to Roger Poisson</p> | |
194 """) | |
195 _dialog = dialog.GenericDialog("About", _about) | |
196 _dialog.show() | |
197 | |
198 #Contact menu | |
199 def onManageContactGroups(self): | |
200 """Open the contact groups manager.""" | |
201 | |
202 def onCloseCallback(): | |
203 pass | |
204 | |
205 contact_group.ContactGroupEditor(self.host, None, onCloseCallback) | |
206 | |
207 #Group menu | |
208 def onJoinRoom(self): | |
209 | |
210 def invite(room_jid, contacts): | |
211 for contact in contacts: | |
212 self.host.bridge.call('inviteMUC', None, contact, room_jid) | |
213 | |
214 def join(room_jid, contacts): | |
215 if self.host.whoami: | |
216 nick = self.host.whoami.node | |
217 if room_jid not in [room.bare for room in self.host.room_list]: | |
218 self.host.bridge.call('joinMUC', lambda room_jid: invite(room_jid, contacts), room_jid, nick) | |
219 else: | |
220 self.host.getOrCreateLiberviaWidget(panels.ChatPanel, (room_jid, "group"), True, jid.JID(room_jid).bare) | |
221 invite(room_jid, contacts) | |
222 | |
223 dialog.RoomAndContactsChooser(self.host, join, ok_button="Join", visible=(True, False)) | |
224 | |
225 def onCollectiveRadio(self): | |
226 def callback(room_jid, contacts): | |
227 self.host.bridge.call('launchRadioCollective', None, contacts, room_jid) | |
228 dialog.RoomAndContactsChooser(self.host, callback, ok_button="Choose", title="Collective Radio", visible=(False, True)) | |
229 | |
230 #Game menu | |
231 def onTarotGame(self): | |
232 def onPlayersSelected(room_jid, other_players): | |
233 self.host.bridge.call('launchTarotGame', None, other_players, room_jid) | |
234 dialog.RoomAndContactsChooser(self.host, onPlayersSelected, 3, title="Tarot", title_invite="Please select 3 other players", visible=(False, True)) | |
235 | |
236 def onXiangqiGame(self): | |
237 Window.alert("A Xiangqi game is planed, but not available yet") | |
238 | |
239 #Settings menu | |
240 | |
241 def onAccount(self): | |
242 def gotUI(xml_ui): | |
243 if not xml_ui: | |
244 return | |
245 body = xmlui.XMLUI(self.host, xml_ui) | |
246 _dialog = dialog.GenericDialog("Manage your account", body, options=['NO_CLOSE']) | |
247 body.setCloseCb(_dialog.close) | |
248 _dialog.show() | |
249 self.host.bridge.call('getAccountDialogUI', gotUI) | |
250 | |
251 def onParameters(self): | |
252 def gotParams(xml_ui): | |
253 if not xml_ui: | |
254 return | |
255 body = xmlui.XMLUI(self.host, xml_ui) | |
256 _dialog = dialog.GenericDialog("Parameters", body, options=['NO_CLOSE']) | |
257 body.setCloseCb(_dialog.close) | |
258 _dialog.setSize('80%', '80%') | |
259 _dialog.show() | |
260 self.host.bridge.call('getParamsUI', gotParams) | |
261 | |
262 def removeItemParams(self): | |
263 """Remove the Parameters item from the Settings menu bar.""" | |
264 self.menu_settings.removeItem(self.item_params) | |
265 | |
266 def onAvatarUpload(self): | |
267 body = AvatarUpload() | |
268 _dialog = dialog.GenericDialog("Avatar upload", body, options=['NO_CLOSE']) | |
269 body.setCloseCb(_dialog.close) | |
270 _dialog.setWidth('40%') | |
271 _dialog.show() |