view src/browser/sat_browser/menu.py @ 589:a5019e62c3e9 frontends_multi_profiles

browser side: big refactoring to base Libervia on QuickFrontend, first draft: /!\ not finished, partially working and highly instable - add collections module with an OrderedDict like class - SatWebFrontend inherit from QuickApp - general sat_frontends tools.jid module is used - bridge/json methods have moved to json module - UniBox is partially removed (should be totally removed before merge to trunk) - Signals are now register with the generic registerSignal method (which is called mainly in QuickFrontend) - the generic getOrCreateWidget method from QuickWidgetsManager is used instead of Libervia's specific methods - all Widget are now based more or less directly on QuickWidget - with the new QuickWidgetsManager.getWidgets method, it's no more necessary to check all widgets which are instance of a particular class - ChatPanel and related moved to chat module - MicroblogPanel and related moved to blog module - global and overcomplicated send method has been disabled: each class should manage its own sending - for consistency with other frontends, former ContactPanel has been renamed to ContactList and vice versa - for the same reason, ChatPanel has been renamed to Chat - for compatibility with QuickFrontend, a fake profile is used in several places, it is set to C.PROF_KEY_NONE (real profile is managed server side for obvious security reasons) - changed default url for web panel to SàT website, and contact address to generic SàT contact address - ContactList is based on QuickContactList, UI changes are done in update method - bride call (now json module) have been greatly improved, in particular call can be done in the same way as for other frontends (bridge.method_name(arg1, arg2, ..., callback=cb, errback=eb). Blocking method must be called like async methods due to javascript architecture - in bridge calls, a callback can now exists without errback - hard reload on BridgeSignals remote error has been disabled, a better option should be implemented - use of constants where that make sens, some style improvments - avatars are temporarily disabled - lot of code disabled, will be fixed or removed before merge - various other changes, check diff for more details server side: manage remote exception on getEntityData, removed getProfileJid call, added getWaitingConf, added getRoomsSubjects
author Goffi <goffi@goffi.org>
date Sat, 24 Jan 2015 01:45:39 +0100
parents b07f0fe2763a
children 6016c74ee323
line wrap: on
line source

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

# Libervia: a Salut à Toi frontend
# Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.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/>.

import pyjd  # this is dummy in pyjs
from sat.core.log import getLogger
log = getLogger(__name__)

from sat.core.i18n import _

from sat_frontends.tools import jid

from pyjamas.ui.SimplePanel import SimplePanel
from pyjamas.ui.HTML import HTML
from pyjamas.ui.Frame import Frame
from pyjamas import Window

from constants import Const as C
import file_tools
import xmlui
import panels
import dialog
import contact_group
import base_menu
from base_menu import MenuCmd


class MainMenuBar(base_menu.GenericMenuBar):
    """The main menu bar which is displayed on top of the document"""

    ITEM_TPL = "<img src='media/icons/menu/%s_menu_red.png' />%s"

    def __init__(self, host):
        styles = {'moved_popup': 'menuLastPopup', 'menu_bar': 'mainMenuBar'}
        base_menu.GenericMenuBar.__init__(self, host, vertical=False, styles=styles)

    @classmethod
    def getCategoryHTML(cls, menu_name_i18n, type_):
        return cls.ITEM_TPL % (type_, menu_name_i18n)


class MainMenuPanel(SimplePanel):
    """Container for the main menu bar"""

    def __init__(self, host):
        self.host = host
        SimplePanel.__init__(self)
        self.setStyleName('menuContainer')
        self.menu_bar = MainMenuBar(self.host)

    def addMenuItem(self, *args):
        self.menu_bar.addMenuItem(*args)

    def addCategory(self, *args):
        self.menu_bar.addCategory(*args)

    def createMenus(self):
        self.addMenuItem("General", [_("General"), _("Web widget")], 'home', MenuCmd(self, "onWebWidget"))
        self.addMenuItem("General", [_("General"), _("Disconnect")], 'home', MenuCmd(self, "onDisconnect"))
        self.addCategory("Contacts", _("Contacts"), 'social')  # save the position for this category
        self.addMenuItem("Groups", [_("Groups"), _("Discussion")], 'social', MenuCmd(self, "onJoinRoom"))
        self.addMenuItem("Groups", [_("Groups"), _("Collective radio")], 'social', MenuCmd(self, "onCollectiveRadio"))
        self.addMenuItem("Games", [_("Games"), _("Tarot")], 'games', MenuCmd(self, "onTarotGame"))
        self.addMenuItem("Games", [_("Games"), _("Xiangqi")], 'games', MenuCmd(self, "onXiangqiGame"))

        # additional menus
        self.menu_bar.addCachedMenus(C.MENU_GLOBAL)

        # menu items that should be displayed after the automatically added ones
        self.addMenuItem("Contacts", [_("Contacts"), _("Manage groups")], 'social', MenuCmd(self, "onManageContactGroups"))

        self.menu_bar.addSeparator()

        self.addMenuItem("Help", [_("Help"), _("Social contract")], 'help', MenuCmd(self, "onSocialContract"))
        self.addMenuItem("Help", [_("Help"), _("About")], 'help', MenuCmd(self, "onAbout"))
        self.addMenuItem("Settings", [_("Settings"), _("Account")], 'settings', MenuCmd(self, "onAccount"))
        self.addMenuItem("Settings", [_("Settings"), _("Parameters")], 'settings', MenuCmd(self, "onParameters"))

        # XXX: temporary, will change when a full profile will be managed in SàT
        self.addMenuItem("Settings", [_("Settings"), _("Upload avatar")], 'settings', MenuCmd(self, "onAvatarUpload"))

        self.add(self.menu_bar)

    # General menu
    def onWebWidget(self):
        web_widget = self.host.widgets.getOrCreateWidget(panels.WebPanel, C.WEB_PANEL_DEFAULT_URL, profile=C.PROF_KEY_NONE)
        self.host.setSelected(web_widget)

    def onDisconnect(self):
        def confirm_cb(answer):
            if answer:
                # FIXME: are we sure the triggers finished their jobs when the backend disconnect?
                # FIXME: disconnection on timeout is not handled yet...
                for plugin in self.host.plugins.values():
                    if hasattr(plugin, 'profileDisconnected'):
                        plugin.profileDisconnected()
                log.info("disconnection")
                self.host.bridge.call('disconnect', None)
        _dialog = dialog.ConfirmDialog(confirm_cb, text="Do you really want to disconnect ?")
        _dialog.show()

    def onSocialContract(self):
        _frame = Frame('contrat_social.html')
        _frame.setStyleName('infoFrame')
        _dialog = dialog.GenericDialog("Contrat Social", _frame)
        _dialog.setSize('80%', '80%')
        _dialog.show()

    def onAbout(self):
        _about = HTML("""<b>Libervia</b>, a Salut &agrave; Toi project<br />
<br />
You can contact the authors at <a href="mailto:contact@salut-a-toi.org">contact@salut-a-toi.org</a><br />
Blog available (mainly in french) at <a href="http://www.goffi.org" target="_blank">http://www.goffi.org</a><br />
Project page: <a href="http://salut-a-toi.org"target="_blank">http://salut-a-toi.org</a><br />
<br />
Any help welcome :)
<p style='font-size:small;text-align:center'>This project is dedicated to Roger Poisson</p>
""")
        _dialog = dialog.GenericDialog("About", _about)
        _dialog.show()

    #Contact menu
    def onManageContactGroups(self):
        """Open the contact groups manager."""

        def onCloseCallback():
            pass

        contact_group.ContactGroupEditor(self.host, None, onCloseCallback)

    #Group menu
    def onJoinRoom(self):

        def invite(room_jid, contacts):
            for contact in contacts:
                self.host.bridge.call('inviteMUC', None, contact, room_jid)

        def join(room_jid, contacts):
            if self.host.whoami:
                nick = self.host.whoami.node
                if room_jid not in [room.bare for room in self.host.room_list]:
                    self.host.bridge.call('joinMUC', lambda room_jid: invite(room_jid, contacts), room_jid, nick)
                else:
                    self.host.getOrCreateLiberviaWidget(panels.ChatPanel, {'item': room_jid, 'type_': "group"}, True, jid.JID(room_jid).bare)
                    invite(room_jid, contacts)

        dialog.RoomAndContactsChooser(self.host, join, ok_button="Join", visible=(True, False))

    def onCollectiveRadio(self):
        def callback(room_jid, contacts):
            self.host.bridge.call('launchRadioCollective', None, contacts, room_jid)
        dialog.RoomAndContactsChooser(self.host, callback, ok_button="Choose", title="Collective Radio", visible=(False, True))

    #Game menu
    def onTarotGame(self):
        def onPlayersSelected(room_jid, other_players):
            self.host.bridge.call('launchTarotGame', None, other_players, room_jid)
        dialog.RoomAndContactsChooser(self.host, onPlayersSelected, 3, title="Tarot", title_invite="Please select 3 other players", visible=(False, True))

    def onXiangqiGame(self):
        Window.alert("A Xiangqi game is planed, but not available yet")

    #Settings menu

    def onAccount(self):
        def gotUI(xml_ui):
            if not xml_ui:
                return
            body = xmlui.create(self.host, xml_ui)
            _dialog = dialog.GenericDialog("Manage your account", body, options=['NO_CLOSE'])
            body.setCloseCb(_dialog.close)
            _dialog.show()
        self.host.bridge.call('getAccountDialogUI', gotUI)

    def onParameters(self):
        def gotParams(xml_ui):
            if not xml_ui:
                return
            body = xmlui.create(self.host, xml_ui)
            _dialog = dialog.GenericDialog("Parameters", body, options=['NO_CLOSE'])
            body.setCloseCb(_dialog.close)
            _dialog.setSize('80%', '80%')
            _dialog.show()
        self.host.bridge.call('getParamsUI', gotParams)

    def removeItemParams(self):
        """Remove the Parameters item from the Settings menu bar."""
        self.menu_settings.removeItem(self.item_params)

    def onAvatarUpload(self):
        body = file_tools.AvatarUpload()
        _dialog = dialog.GenericDialog("Avatar upload", body, options=['NO_CLOSE'])
        body.setCloseCb(_dialog.close)
        _dialog.setWidth('40%')
        _dialog.show()