changeset ecbc91b24883 in /home/hg/repos/gajim

details:http://hg.gajim.org/gajim?cmd=changeset;node=ecbc91b24883
description: plugin to add whiteboard feature. Fixes #2970

diffstat:

 plugins/whiteboard/__init__.py          |    1 +
 plugins/whiteboard/brush_tool.png       |    0 
 plugins/whiteboard/line_tool.png        |    0 
 plugins/whiteboard/manifest.ini         |    7 +
 plugins/whiteboard/oval_tool.png        |    0 
 plugins/whiteboard/plugin.py            |  453 ++++++++++++++++++++++++++++++++
 plugins/whiteboard/whiteboard.png       |    0 
 plugins/whiteboard/whiteboard_widget.py |  416 +++++++++++++++++++++++++++++
 plugins/whiteboard/whiteboard_widget.ui |  324 ++++++++++++++++++++++
 9 files changed, 1201 insertions(+), 0 deletions(-)

diffs (truncated from 1229 to 300 lines):

diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/__init__.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/whiteboard/__init__.py    Mon Nov 01 14:30:23 2010 +0100
@@ -0,0 +1,1 @@
+from plugin import WhiteboardPlugin
diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/brush_tool.png
Binary file plugins/whiteboard/brush_tool.png has changed
diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/line_tool.png
Binary file plugins/whiteboard/line_tool.png has changed
diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/manifest.ini
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/whiteboard/manifest.ini   Mon Nov 01 14:30:23 2010 +0100
@@ -0,0 +1,7 @@
+[info]
+name: Whiteboard
+short_name: whiteboard
+version: 0.1
+description: Shows a whiteboard in chat.
+authors = Yann Leboulanger <[email protected]>
+homepage = www.gajim.org
diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/oval_tool.png
Binary file plugins/whiteboard/oval_tool.png has changed
diff -r a27c12733243 -r ecbc91b24883 plugins/whiteboard/plugin.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/whiteboard/plugin.py      Mon Nov 01 14:30:23 2010 +0100
@@ -0,0 +1,453 @@
+## plugins/whiteboard/plugin.py
+##
+## Copyright (C) 2009 Jeff Ling <jeff.ummu AT gmail.com>
+## Copyright (C) 2010 Yann Leboulanger <asterix AT lagaule.org>
+##
+## This file is part of Gajim.
+##
+## Gajim is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published
+## by the Free Software Foundation; version 3 only.
+##
+## Gajim 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
+##
+
+'''
+Whiteboard plugin.
+
+:author: Yann Leboulanger <[email protected]>
+:since: 1st November 2010
+:copyright: Copyright (2010) Yann Leboulanger <[email protected]>
+:license: GPL
+'''
+
+
+from common import helpers
+from common import gajim
+from plugins import GajimPlugin
+from plugins.helpers import log_calls, log
+import common.xmpp
+import gtk
+import chat_control
+from common import ged
+from common.jingle_session import JingleSession
+from common.jingle_content import JingleContent
+from common.jingle_transport import JingleTransport, TransportType
+import dialogs
+from whiteboard_widget import Whiteboard
+from common import xmpp
+from common import caps_cache
+
+NS_JINGLE_XHTML = 'urn:xmpp:tmp:jingle:apps:xhtml'
+NS_JINGLE_SXE = 'urn:xmpp:tmp:jingle:transports:sxe'
+NS_SXE = 'urn:xmpp:sxe:0'
+
+class WhiteboardPlugin(GajimPlugin):
+    @log_calls('WhiteboardPlugin')
+    def init(self):
+        self.config_dialog = None
+        self.events_handlers = {
+            'jingle-request-received': (ged.GUI1, self._nec_jingle_received),
+            'jingle-connected-received': (ged.GUI1, 
self._nec_jingle_connected),
+            'jingle-disconnected-received': (ged.GUI1,
+                self._nec_jingle_disconnected),
+            'raw-message-received': (ged.GUI1, self._nec_raw_message),
+        }
+        self.gui_extension_points = {
+            'chat_control_base' : (self.connect_with_chat_control,
+                self.disconnect_from_chat_control),
+            'chat_control_base_update_toolbar': (self.update_button_state,
+                None),
+        }
+        self.controls = []
+        self.sid = None
+
+    @log_calls('WhiteboardPlugin')
+    def _compute_caps_hash(self):
+        for a in gajim.connections:
+            gajim.caps_hash[a] = caps_cache.compute_caps_hash([
+                gajim.gajim_identity], gajim.gajim_common_features + 
gajim.gajim_optional_features[a])
+        # re-send presence with new hash
+        connected = gajim.connections[a].connected
+        if connected > 1 and gajim.SHOW_LIST[connected] != 'invisible':
+            gajim.connections[a].change_status(gajim.SHOW_LIST[connected],
+                gajim.connections[a].status)
+
+    @log_calls('WhiteboardPlugin')
+    def activate(self):
+        if NS_JINGLE_SXE not in gajim.gajim_common_features:
+            gajim.gajim_common_features.append(NS_JINGLE_SXE)
+        if NS_SXE not in gajim.gajim_common_features:
+            gajim.gajim_common_features.append(NS_SXE)
+        self._compute_caps_hash()
+
+    @log_calls('WhiteboardPlugin')
+    def deactivate(self):
+        if NS_JINGLE_SXE in gajim.gajim_common_features:
+            gajim.gajim_common_features.remove(NS_JINGLE_SXE)
+        if NS_SXE in gajim.gajim_common_features:
+            gajim.gajim_common_features.remove(NS_SXE)
+        self._compute_caps_hash()
+
+    @log_calls('WhiteboardPlugin')
+    def connect_with_chat_control(self, control):
+        if isinstance(control, chat_control.ChatControl):
+            base = Base(self, control)
+            self.controls.append(base)
+
+    @log_calls('WhiteboardPlugin')
+    def disconnect_from_chat_control(self, chat_control):
+        for base in self.controls:
+            base.disconnect_from_chat_control()
+        self.controls = []
+
+    @log_calls('WhiteboardPlugin')
+    def update_button_state(self, control):
+        for base in self.controls:
+            if base.chat_control == control:
+                if control.contact.supports(NS_JINGLE_SXE) and \
+                control.contact.supports(NS_SXE):
+                    base.button.set_sensitive(True)
+                else:
+                    base.button.set_sensitive(False)
+
+    @log_calls('WhiteboardPlugin')
+    def show_request_dialog(self, account, fjid, jid, sid, content_types):
+        def on_ok():
+            session = gajim.connections[account].get_jingle_session(fjid, sid)
+            self.sid = session.sid
+            if not session.accepted:
+                session.approve_session()
+            for content in content_types:
+                session.approve_content(content)
+            for _jid in (fjid, jid):
+                ctrl = gajim.interface.msg_win_mgr.get_control(_jid, account)
+                if ctrl:
+                    break
+            if not ctrl:
+                # create it
+                gajim.interface.new_chat_from_jid(account, jid)
+                ctrl = gajim.interface.msg_win_mgr.get_control(jid, account)
+            session = session.contents[('initiator', 'xhtml')]
+            ctrl.draw_whiteboard(session)
+
+        def on_cancel():
+            session = gajim.connections[account].get_jingle_session(fjid, sid)
+            session.decline_session()
+
+        contact = gajim.contacts.get_first_contact_from_jid(account, jid)
+        if contact:
+            name = contact.get_shown_name()
+        else:
+            name = jid
+        pritext = _('Incoming Whiteboard')
+        sectext = _('%(name)s (%(jid)s) wants to start a whiteboard with '
+            'you. Do you want to accept?') % {'name': name, 'jid': jid}
+        dialog = dialogs.NonModalConfirmationDialog(pritext, sectext=sectext,
+            on_response_ok=on_ok, on_response_cancel=on_cancel)
+        dialog.popup()
+
+    @log_calls('WhiteboardPlugin')
+    def _nec_jingle_received(self, obj):
+        content_types = set(c[0] for c in obj.contents)
+        if 'xhtml' not in content_types:
+            return
+        self.show_request_dialog(obj.conn.name, obj.fjid, obj.jid, obj.sid,
+            content_types)
+
+    @log_calls('WhiteboardPlugin')
+    def _nec_jingle_connected(self, obj):
+        account = obj.conn.name
+        ctrl = (gajim.interface.msg_win_mgr.get_control(obj.fjid, account)
+            or gajim.interface.msg_win_mgr.get_control(obj.jid, account))
+        if not ctrl:
+            return
+        session = gajim.connections[obj.conn.name].get_jingle_session(obj.fjid,
+            obj.sid)
+
+        if ('initiator', 'xhtml') not in session.contents:
+            return
+
+        session = session.contents[('initiator', 'xhtml')]
+        ctrl.draw_whiteboard(session)
+
+    @log_calls('WhiteboardPlugin')
+    def _nec_jingle_disconnected(self, obj):
+        for base in self.controls:
+            if base.sid == obj.sid:
+                base.stop_whiteboard()
+
+    @log_calls('WhiteboardPlugin')
+    def _nec_raw_message(self, obj):
+        if obj.stanza.getTag('sxe', namespace=NS_SXE):
+            account = obj.conn.name
+
+            try:
+                fjid = helpers.get_full_jid_from_iq(obj.stanza)
+            except helpers.InvalidFormat:
+                obj.conn.dispatch('ERROR', (_('Invalid Jabber ID'),
+                    _('A message from a non-valid JID arrived, it has been '
+                      'ignored.')))
+
+            jid = gajim.get_jid_without_resource(fjid)
+            ctrl = (gajim.interface.msg_win_mgr.get_control(fjid, account)
+                or gajim.interface.msg_win_mgr.get_control(jid, account))
+            if not ctrl:
+                return
+            sxe = obj.stanza.getTag('sxe')
+            if not sxe:
+                return
+            sid = sxe.getAttr('session')
+            if (jid, sid) not in obj.conn._sessions:
+                pass
+#                newjingle = JingleSession(con=self, weinitiate=False, 
jid=jid, sid=sid)
+#                self.addJingle(newjingle)
+
+            # we already have such session in dispatcher...
+            session = obj.conn.get_jingle_session(fjid, sid)
+            cn = session.contents[('initiator', 'xhtml')]
+            error = obj.stanza.getTag('error')
+            if error:
+                action = 'iq-error'
+            else:
+                action = 'edit'
+
+            cn.on_stanza(obj.stanza, sxe, error, action)
+#        def __editCB(self, stanza, content, error, action):
+            #new_tags = sxe.getTags('new')
+            #remove_tags = sxe.getTags('remove')
+
+            #if new_tags is not None:
+                ## Process new elements
+                #for tag in new_tags:
+                    #if tag.getAttr('type') == 'element':
+                        #ctrl.whiteboard.recieve_element(tag)
+                    #elif tag.getAttr('type') == 'attr':
+                        #ctrl.whiteboard.recieve_attr(tag)
+                #ctrl.whiteboard.apply_new()
+
+            #if remove_tags is not None:
+                ## Delete rids
+                #for tag in remove_tags:
+                    #target = tag.getAttr('target')
+                    #ctrl.whiteboard.image.del_rid(target)
+
+            # Stop propagating this event, it's handled
+            return True
+
+
+class Base(object):
+    def __init__(self, plugin, chat_control):
+        self.plugin = plugin
+        self.chat_control = chat_control
+        self.chat_control.draw_whiteboard = self.draw_whiteboard
+        self.contact = self.chat_control.contact
+        self.account = self.chat_control.account
+        self.jid = self.contact.get_full_jid()
+        self.create_buttons()
+        self.whiteboard = None
+        self.sid = None
+
+    def create_buttons(self):
+        # create juick button
+        actions_hbox = self.chat_control.xml.get_object('actions_hbox')
+        self.button = gtk.ToggleButton(label=None, use_underline=True)
+        self.button.set_property('relief', gtk.RELIEF_NONE)
+        self.button.set_property('can-focus', False)
+        img = gtk.Image()
+        img_path = self.plugin.local_file_path('whiteboard.png')
+        pixbuf = gtk.gdk.pixbuf_new_from_file(img_path)
+        iconset = gtk.IconSet(pixbuf=pixbuf)
+        factory = gtk.IconFactory()
+        factory.add('whiteboard', iconset)
+        factory.add_default()
+        img.set_from_stock('whiteboard', gtk.ICON_SIZE_BUTTON)
+        self.button.set_image(img)
+        send_button = self.chat_control.xml.get_object('send_button')
+        send_button_pos = actions_hbox.child_get_property(send_button,
+            'position')
_______________________________________________
Commits mailing list
[email protected]
http://lists.gajim.org/cgi-bin/listinfo/commits

Reply via email to