diff --git a/src/common/connection.py b/src/common/connection.py index 2740d6d77..a2f31fcbf 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -820,14 +820,14 @@ class Connection(ConnectionHandlers): self.connection.send(msg_iq) - def send_message(self, jid, msg, keyID, type = 'chat', subject='', - chatstate = None, msg_id = None, composing_xep = None, resource = None, - user_nick = None, xhtml = None, session = None, forward_from = None): + def send_message(self, jid, msg, keyID, type='chat', subject='', + chatstate=None, msg_id=None, composing_xep=None, resource=None, + user_nick=None, xhtml=None, session=None, forward_from=None, form_node=None): if not self.connection: return 1 if msg and not xhtml and gajim.config.get('rst_formatting_outgoing_messages'): xhtml = create_xhtml(msg) - if not msg and chatstate is None: + if not msg and chatstate is None and form_node is None: return 2 fjid = jid if resource: @@ -866,6 +866,9 @@ class Connection(ConnectionHandlers): if msgenc: msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc) + if form_node: + msg_iq.addChild(node=form_node) + # JEP-0172: user_nickname if user_nick: msg_iq.setTag('nick', namespace = common.xmpp.NS_NICK).setData( diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index b75091f97..e9b27a638 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1551,6 +1551,11 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('GC_INVITATION', (room_jid, frm, '', None, is_continued)) return + form_node = None + for xtag in xtags: + if xtag.getNamespace() == common.xmpp.NS_DATA: + form_node = xtag + break # chatstates - look for chatstate tags in a message if not delayed if not delayed: composing_xep = False @@ -1658,7 +1663,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, mtype = treat_as self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, subject, chatstate, msg_id, composing_xep, user_nick, msghtml, - session)) + session, form_node)) # END messageCB def get_session(self, jid, thread_id, type): diff --git a/src/dialogs.py b/src/dialogs.py index bfe258417..994485b46 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -29,6 +29,7 @@ import gtkgui_helpers import vcard import conversation_textview import message_control +import dataforms_widget from random import randrange @@ -46,6 +47,7 @@ from advanced import AdvancedConfigurationWindow from common import gajim from common import helpers +from common import dataforms from common.exceptions import GajimGeneralException class EditGroupsDialog: @@ -1756,8 +1758,8 @@ class SingleMessageWindow: singled message depending on action argument which can be 'send' or 'receive'. ''' - def __init__(self, account, to = '', action = '', from_whom = '', - subject = '', message = '', resource = '', session = None): + def __init__(self, account, to='', action='', from_whom='', subject='', + message='', resource='', session=None, form_node=None): self.account = account self.action = action @@ -1788,6 +1790,18 @@ class SingleMessageWindow: self.conversation_tv_buffer = self.conversation_textview.tv.get_buffer() self.xml.get_widget('conversation_scrolledwindow').add( self.conversation_textview.tv) + + self.form_widget = None + parent_box = self.xml.get_widget('conversation_scrolledwindow').get_parent() + if form_node: + dataform = dataforms.ExtendForm(node = form_node) + self.form_widget = dataforms_widget.DataFormWidget(dataform) + self.form_widget.show_all() + parent_box.add(self.form_widget) + parent_box.child_set_property(self.form_widget, 'position', + parent_box.child_get_property(self.xml.get_widget('conversation_scrolledwindow'), 'position')) + self.action = 'form' + self.send_button = self.xml.get_widget('send_button') self.reply_button = self.xml.get_widget('reply_button') self.send_and_close_button = self.xml.get_widget('send_and_close_button') @@ -1917,6 +1931,17 @@ class SingleMessageWindow: self.reply_button.grab_focus() self.cancel_button.hide() self.close_button.show() + elif action == 'form': # prepare UI for Receiving + title = _('Form %s') % title + self.send_button.show() + self.send_and_close_button.show() + self.to_label.show() + self.to_entry.show() + self.reply_button.hide() + self.from_label.hide() + self.from_entry.hide() + self.conversation_scrolledwindow.hide() + self.message_scrolledwindow.hide() self.window.set_title(title) @@ -1960,9 +1985,14 @@ class SingleMessageWindow: else: session = gajim.connections[self.account].make_new_session(to_whom_jid) + if self.form_widget: + form_node = self.form_widget.data_form + else: + form_node = None # FIXME: allow GPG message some day gajim.connections[self.account].send_message(to_whom_jid, message, - keyID = None, type = 'normal', subject=subject, session = session) + keyID=None, type='normal', subject=subject, session=session, + form_node=form_node) self.subject_entry.set_text('') # we sent ok, clear the subject self.message_tv_buffer.set_text('') # we sent ok, clear the textview diff --git a/src/gajim.py b/src/gajim.py index b36b53ddc..c89427d54 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -698,7 +698,7 @@ class Interface: def handle_event_msg(self, account, array): # 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject, - # chatstate, msg_id, composing_xep, user_nick, xhtml, session)) + # chatstate, msg_id, composing_xep, user_nick, xhtml, session, form_node)) # user_nick is JEP-0172 full_jid_with_resource = array[0] @@ -806,12 +806,13 @@ class Interface: if encrypted: self.roster.on_message(jid, message, array[2], account, array[3], msg_type, subject, resource, msg_id, array[9], - advanced_notif_num, session = session) + advanced_notif_num, session=session, form_node=array[12]) else: # xhtml in last element self.roster.on_message(jid, message, array[2], account, array[3], msg_type, subject, resource, msg_id, array[9], - advanced_notif_num, xhtml = xhtml, session = session) + advanced_notif_num, xhtml=xhtml, session=session, + form_node=array[12]) nickname = gajim.get_name_from_jid(account, jid) # Check and do wanted notifications msg = message diff --git a/src/roster_window.py b/src/roster_window.py index aae5fd2f0..e48999807 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -3842,9 +3842,9 @@ class RosterWindow: is_continued=is_continued) mw.new_tab(gc_control) - def on_message(self, jid, msg, tim, account, encrypted = False, - msg_type = '', subject = None, resource = '', msg_id = None, - user_nick = '', advanced_notif_num = None, xhtml = None, session = None): + def on_message(self, jid, msg, tim, account, encrypted=False, msg_type='', + subject=None, resource='', msg_id=None, user_nick='', + advanced_notif_num=None, xhtml=None, session=None, form_node=None): '''when we receive a message''' contact = None # if chat window will be for specific resource @@ -3899,9 +3899,9 @@ class RosterWindow: popup = helpers.allow_popup_window(account, advanced_notif_num) if msg_type == 'normal' and popup: # it's single message to be autopopuped - dialogs.SingleMessageWindow(account, contact.jid, - action = 'receive', from_whom = jid, subject = subject, - message = msg, resource = resource, session = session) + dialogs.SingleMessageWindow(account, contact.jid, action='receive', + from_whom=jid, subject=subject, message=msg, resource=resource, + session=session, form_node=form_node) return # We print if window is opened and it's not a single message @@ -3926,12 +3926,12 @@ class RosterWindow: show_in_roster = notify.get_show_in_roster(event_type, account, contact) show_in_systray = notify.get_show_in_systray(event_type, account, contact) event = gajim.events.create_event(type_, (msg, subject, msg_type, tim, - encrypted, resource, msg_id, xhtml, session), show_in_roster = show_in_roster, - show_in_systray = show_in_systray) + encrypted, resource, msg_id, xhtml, session, form_node), + show_in_roster=show_in_roster, show_in_systray=show_in_systray) gajim.events.add_event(account, fjid, event) if popup: if not ctrl: - self.new_chat(contact, account, resource = resource_for_chat) + self.new_chat(contact, account, resource=resource_for_chat) if path and not self.dragging and gajim.config.get( 'scroll_roster_to_last_message'): # we curently see contact in our roster OR he @@ -4196,8 +4196,8 @@ class RosterWindow: ft = gajim.interface.instances['file_transfers'] if event.type_ == 'normal': dialogs.SingleMessageWindow(account, jid, - action = 'receive', from_whom = jid, subject = data[1], - message = data[0], resource = data[5], session = data[8]) + action='receive', from_whom=jid, subject=data[1], message=data[0], + resource=data[5], session=data[8], form_node=data[9]) gajim.interface.remove_first_event(account, jid, event.type_) return True elif event.type_ == 'file-request':