Hello.

I'd like to commit  chatstates_iris and maybe jabber_gone
I'm posting here in order to ask for review because it may be considered as 
new feature.  patches are quite small anyway.

BACKGROUND:
Currently, Kopete uses JEP-0022 [1] for typing notification. Most of ancient 
client implement it.
Anyway, new client now implement JEP-0085 [2] . Some client implement only it 
(gtalk, libgaim based clients, ...)

PATCHES:
the attached chatstates_iris.diff is a patch against libiris (in the 0.12 
branch) to implement the new jep on the old one.
I'd like to commit it, this is not really a new feature, since users may think 
typing notification are broken.  (we received already a bug report [3])

The second patch (jabber_gone) is a patch to Kopete 0.12, that implement a new 
feature provided by JEP-0085: the ability to know when the user closes his 
window
This is a new feature, should I commit ?

PSI:
the psi guys have also implemented the JEP-0085, but a bit differently:
(see the chatstates_psi.diff patch)
their way is more complex, but more low)level to the protocol itself. And it 
require much ore change in the client.   We probably should go that way in 
KDE4
(i only had their patch after having implemented it)


[1] http://www.jabber.org/jeps/jep-0022.html
[2] http://www.jabber.org/jeps/jep-0085.html
[3] https://bugs.kde.org/show_bug.cgi?id=121507


PS: i wanted to also implement the jep-0183 , but it's too late, i must have 
done that yesterday :-) . 
Index: iris/include/im.h
===================================================================
--- iris/include/im.h   (revision 525193)
+++ iris/include/im.h   (working copy)
@@ -49,7 +49,7 @@
        typedef QValueList<Url> UrlList;
        typedef QMap<QString, QString> StringMap;
        typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
-                       ComposingEvent, CancelEvent } MsgEvent;
+                       ComposingEvent, CancelEvent, InactiveEvent, GoneEvent } 
MsgEvent;
                                            
        class Message
        {
Index: iris/xmpp-im/types.cpp
===================================================================
--- iris/xmpp-im/types.cpp      (revision 525193)
+++ iris/xmpp-im/types.cpp      (working copy)
@@ -544,6 +544,8 @@
                        else
                                
x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
                }
+               else
+                       s.appendChild(  s.createElement(NS_CHATSTATES , 
"active" ) );
 
                for(QValueList<MsgEvent>::ConstIterator ev = 
d->eventList.begin(); ev != d->eventList.end(); ++ev) {
                        switch (*ev) {
@@ -558,14 +560,26 @@
                                        break;
                                case ComposingEvent: 
                                        
x.appendChild(s.createElement("jabber:x:event", "composing"));
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "composing" ) ); 
                                        break;
                                case CancelEvent:
-                                       // Add nothing
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "paused" ) ); 
                                        break;
+                               case InactiveEvent:
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "inactive" ) ); 
+                                       break;
+                               case GoneEvent:
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "gone" ) ); 
+                                       break;
                        }
                }
                s.appendChild(x);
-       } 
+       }
+               
 
        // xencrypted
        if(!d->xencrypted.isEmpty())
@@ -595,6 +609,7 @@
        d->subject.clear();
        d->body.clear();
        d->thread = QString();
+       d->eventList.clear();
 
        QDomElement root = s.element();
 
@@ -631,6 +646,33 @@
                                        }
                                }
                        }
+                       else if (e.namespaceURI() == NS_CHATSTATES)
+                       {
+                               if(e.tagName() == "active")
+                               {
+                                       //like in JEP-0022  we let the client 
know that we can receive ComposingEvent
+                                       // (we can do that according to  §4.6  
of the JEP-0085)
+                                       d->eventList += ComposingEvent;
+                                       d->eventList += InactiveEvent;
+                                       d->eventList += GoneEvent;
+                               }
+                               else if (e.tagName() == "composing")
+                               {
+                                       d->eventList += ComposingEvent;
+                               }
+                               else if (e.tagName() == "paused")
+                               {
+                                       d->eventList += CancelEvent;
+                               }
+                               else if (e.tagName() == "inactive")
+                               {
+                                       d->eventList += InactiveEvent;
+                               }
+                               else if (e.tagName() == "gone")
+                               {
+                                       d->eventList += GoneEvent;
+                               }
+                       }
                        else {
                                //printf("extension element: [%s]\n", 
e.tagName().latin1());
                        }
@@ -664,7 +706,6 @@
        }
        
     // events
-       d->eventList.clear();
        nl = root.elementsByTagNameNS("jabber:x:event", "x");
        if (nl.count()) {
                nl = nl.item(0).childNodes();
Index: iris/xmpp-core/protocol.h
===================================================================
--- iris/xmpp-core/protocol.h   (revision 525193)
+++ iris/xmpp-core/protocol.h   (working copy)
@@ -37,6 +37,7 @@
 #define NS_BIND     "urn:ietf:params:xml:ns:xmpp-bind"
 #define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im";
 #define NS_XHTML "http://www.w3.org/1999/xhtml";
+#define NS_CHATSTATES "http://jabber.org/protocol/chatstates";
 
 namespace XMPP
 {
Index: jabbercontact.h
===================================================================
--- jabbercontact.h     (revision 525193)
+++ jabbercontact.h     (working copy)
@@ -255,16 +255,17 @@
         * Indicates whether the vCard is currently
         * being updated or not.
         */
-       bool mVCardUpdateInProgress;
+       bool mVCardUpdateInProgress :1;
 
-       bool mRequestComposingEvent;
-       bool mRequestOfflineEvent;
-       bool mRequestDisplayedEvent;
-       bool mRequestDeliveredEvent;
+       bool mRequestComposingEvent :1;
+       bool mRequestOfflineEvent :1;
+       bool mRequestDisplayedEvent :1;
+       bool mRequestDeliveredEvent :1;
+       bool mRequestGoneEvent :1;
        /**
         * tell if the disco#info has been done for this contact.
         */
-       bool mDiscoDone;
+       bool mDiscoDone :1;
 
        QString mLastReceivedMessageId;
        QTimer *m_syncTimer;
Index: libiris/iris/include/im.h
===================================================================
--- libiris/iris/include/im.h   (revision 525193)
+++ libiris/iris/include/im.h   (working copy)
@@ -49,7 +49,7 @@
        typedef QValueList<Url> UrlList;
        typedef QMap<QString, QString> StringMap;
        typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
-                       ComposingEvent, CancelEvent } MsgEvent;
+                       ComposingEvent, CancelEvent, InactiveEvent, GoneEvent } 
MsgEvent;
                                            
        class Message
        {
Index: libiris/iris/xmpp-im/types.cpp
===================================================================
--- libiris/iris/xmpp-im/types.cpp      (revision 525193)
+++ libiris/iris/xmpp-im/types.cpp      (working copy)
@@ -544,6 +544,8 @@
                        else
                                
x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
                }
+               else
+                       s.appendChild(  s.createElement(NS_CHATSTATES , 
"active" ) );
 
                for(QValueList<MsgEvent>::ConstIterator ev = 
d->eventList.begin(); ev != d->eventList.end(); ++ev) {
                        switch (*ev) {
@@ -558,14 +560,26 @@
                                        break;
                                case ComposingEvent: 
                                        
x.appendChild(s.createElement("jabber:x:event", "composing"));
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "composing" ) ); 
                                        break;
                                case CancelEvent:
-                                       // Add nothing
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "paused" ) ); 
                                        break;
+                               case InactiveEvent:
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "inactive" ) ); 
+                                       break;
+                               case GoneEvent:
+                                       if (d->body.isEmpty())
+                                               s.appendChild(  
s.createElement(NS_CHATSTATES , "gone" ) ); 
+                                       break;
                        }
                }
                s.appendChild(x);
-       } 
+       }
+               
 
        // xencrypted
        if(!d->xencrypted.isEmpty())
@@ -595,6 +609,7 @@
        d->subject.clear();
        d->body.clear();
        d->thread = QString();
+       d->eventList.clear();
 
        QDomElement root = s.element();
 
@@ -631,6 +646,33 @@
                                        }
                                }
                        }
+                       else if (e.namespaceURI() == NS_CHATSTATES)
+                       {
+                               if(e.tagName() == "active")
+                               {
+                                       //like in JEP-0022  we let the client 
know that we can receive ComposingEvent
+                                       // (we can do that according to  §4.6  
of the JEP-0085)
+                                       d->eventList += ComposingEvent;
+                                       d->eventList += InactiveEvent;
+                                       d->eventList += GoneEvent;
+                               }
+                               else if (e.tagName() == "composing")
+                               {
+                                       d->eventList += ComposingEvent;
+                               }
+                               else if (e.tagName() == "paused")
+                               {
+                                       d->eventList += CancelEvent;
+                               }
+                               else if (e.tagName() == "inactive")
+                               {
+                                       d->eventList += InactiveEvent;
+                               }
+                               else if (e.tagName() == "gone")
+                               {
+                                       d->eventList += GoneEvent;
+                               }
+                       }
                        else {
                                //printf("extension element: [%s]\n", 
e.tagName().latin1());
                        }
@@ -664,7 +706,6 @@
        }
        
     // events
-       d->eventList.clear();
        nl = root.elementsByTagNameNS("jabber:x:event", "x");
        if (nl.count()) {
                nl = nl.item(0).childNodes();
Index: libiris/iris/xmpp-core/protocol.h
===================================================================
--- libiris/iris/xmpp-core/protocol.h   (revision 525193)
+++ libiris/iris/xmpp-core/protocol.h   (working copy)
@@ -37,6 +37,7 @@
 #define NS_BIND     "urn:ietf:params:xml:ns:xmpp-bind"
 #define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im";
 #define NS_XHTML "http://www.w3.org/1999/xhtml";
+#define NS_CHATSTATES "http://jabber.org/protocol/chatstates";
 
 namespace XMPP
 {
Index: jabberchatsession.h
===================================================================
--- jabberchatsession.h (revision 525193)
+++ jabberchatsession.h (working copy)
@@ -40,7 +40,9 @@
        JabberChatSession ( JabberProtocol *protocol, const JabberBaseContact 
*user,
                                                   Kopete::ContactPtrList 
others, const QString &resource = "",
                                                   const char *name = 0 );
-
+       
+       ~JabberChatSession();
+       
        /**
         * @brief Get the local user in the session
         * @return the local user in the session, same as account()->myself()
Index: jabbercontact.cpp
===================================================================
--- jabbercontact.cpp   (revision 525193)
+++ jabbercontact.cpp   (working copy)
@@ -117,6 +117,7 @@
        mRequestDisplayedEvent = false;
        mRequestDeliveredEvent = false;
        mRequestComposingEvent = false;
+       mRequestGoneEvent = false;
        mDiscoDone = false;
 }
 
@@ -294,14 +295,25 @@
                        {
                        mManager->receivedEventNotification( i18n("Message 
stored on the server, contact offline") );
                        }
+                       else if (message.containsEvent ( XMPP::GoneEvent ) )
+                       {
+                               if(mManager->view( 
Kopete::Contact::CannotCreate ))
+                               {   //show an internal message if the user has 
not already closed his window
+                                       Kopete::Message m=Kopete::Message ( 
this, mManager->members(),
+                                               i18n("%1 has ended their 
participation in the chat session.").arg(metaContact()->displayName()),
+                                               Kopete::Message::Internal  );
+                                       mManager->appendMessage ( m, 
message.from().resource () );
+                               }
+                       }
                }
                else
                // Then here could be event notification requests
                {
-                       mRequestComposingEvent = message.containsEvent ( 
XMPP::ComposingEvent ) ? true : false;
-                       mRequestOfflineEvent = message.containsEvent ( 
XMPP::OfflineEvent ) ? true : false;
-                       mRequestDeliveredEvent = message.containsEvent ( 
XMPP::DeliveredEvent ) ? true : false;
-                       mRequestDisplayedEvent = message.containsEvent ( 
XMPP::DisplayedEvent) ? true : false;
+                       mRequestComposingEvent = message.containsEvent ( 
XMPP::ComposingEvent );
+                       mRequestOfflineEvent = message.containsEvent ( 
XMPP::OfflineEvent );
+                       mRequestDeliveredEvent = message.containsEvent ( 
XMPP::DeliveredEvent );
+                       mRequestDisplayedEvent = message.containsEvent ( 
XMPP::DisplayedEvent);
+                       mRequestGoneEvent= message.containsEvent ( 
XMPP::GoneEvent);
                }
        }
 
@@ -1463,6 +1475,8 @@
                return mRequestComposingEvent;
        else if ( event == CancelEvent )
                return mRequestComposingEvent;
+       else if ( event == GoneEvent )
+               return mRequestGoneEvent;
        else
                return false;
 }
Index: jabberchatsession.cpp
===================================================================
--- jabberchatsession.cpp       (revision 525193)
+++ jabberchatsession.cpp       (working copy)
@@ -74,6 +74,12 @@
 
 }
 
+JabberChatSession::~JabberChatSession( )
+{
+       sendNotification( XMPP::GoneEvent );
+}
+
+
 void JabberChatSession::slotUpdateDisplayName ()
 {
        kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << endl;
@@ -310,6 +316,7 @@
 
 }
 
+
 #include "jabberchatsession.moc"
 
 // vim: set noet ts=4 sts=4 sw=4:
Sun Feb 26 22:20:50 CET 2006  Remko Troncon <[EMAIL PROTECTED]>
  * Chat states.
diff -rN -u old-psi-mainline/iris/include/im.h new-psi-mainline/iris/include/im.h
--- old-psi-mainline/iris/include/im.h	2006-04-01 15:42:18.000000000 +0200
+++ new-psi-mainline/iris/include/im.h	2006-04-01 15:42:18.000000000 +0200
@@ -51,6 +51,8 @@
 	typedef QMap<QString, QString> StringMap;
 	typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent,
 			ComposingEvent, CancelEvent } MsgEvent;
+	typedef enum { StateNone, StateActive, StateComposing, StatePaused, 
+			StateInactive, StateGone } ChatState;
                                            
 	class Message
 	{
@@ -96,6 +98,10 @@
 		bool containsEvents() const;
 		bool containsEvent(MsgEvent e) const;
 		void addEvent(MsgEvent e);
+
+		// JEP-0085
+		ChatState chatState() const;
+		void setChatState(ChatState);
  
 		// JEP-0027
 		QString xencrypted() const;
@@ -286,6 +292,7 @@
 		bool canGroupchat() const;
 		bool canVoice() const;
 		bool canDisco() const;
+		bool canChatState() const;
 		bool isGateway() const;
 		bool haveVCard() const;
 
diff -rN -u old-psi-mainline/iris/xmpp-im/types.cpp new-psi-mainline/iris/xmpp-im/types.cpp
--- old-psi-mainline/iris/xmpp-im/types.cpp	2006-04-01 15:42:18.000000000 +0200
+++ new-psi-mainline/iris/xmpp-im/types.cpp	2006-04-01 15:42:19.000000000 +0200
@@ -192,6 +192,7 @@
 	QList<MsgEvent> eventList;
 	QString eventId;
 	QString xencrypted, invite;
+	ChatState chatState;
 
 	bool spooled, wasEncrypted;
 };
@@ -210,6 +211,7 @@
 	d->spooled = false;
 	d->wasEncrypted = false;
 	d->errorCode = -1;*/
+	d->chatState = StateNone;
 }
 
 //! \brief Constructs a copy of Message object
@@ -422,6 +424,16 @@
 	}
 }
 
+ChatState Message::chatState() const
+{
+	return d->chatState;
+}
+
+void Message::setChatState(ChatState state)
+{
+	d->chatState = state;
+}
+
 QString Message::xencrypted() const
 {
 	return d->xencrypted;
@@ -544,6 +556,30 @@
 		s.appendChild(x);
 	} 
 
+	// chat state
+	QString chatStateNS = "http://jabber.org/protocol/chatstates";;
+	if (d->chatState != StateNone) {
+		switch(d->chatState) {
+			case StateActive:
+				s.appendChild(s.createElement(chatStateNS, "active"));
+				break;
+			case StateComposing:
+				s.appendChild(s.createElement(chatStateNS, "composing"));
+				break;
+			case StatePaused:
+				s.appendChild(s.createElement(chatStateNS, "paused"));
+				break;
+			case StateInactive:
+				s.appendChild(s.createElement(chatStateNS, "inactive"));
+				break;
+			case StateGone:
+				s.appendChild(s.createElement(chatStateNS, "gone"));
+				break;
+			default: 
+				break;
+		}
+	}
+
 	// xencrypted
 	if(!d->xencrypted.isEmpty())
 		s.appendChild(s.createTextElement("jabber:x:encrypted", "x", d->xencrypted));
@@ -646,6 +682,25 @@
 			d->eventList += CancelEvent;
 	}
 
+	// Chat states
+	QString chatStateNS = "http://jabber.org/protocol/chatstates";;
+	t = root.elementsByTagNameNS(chatStateNS, "active").item(0).toElement();
+	if(!t.isNull())
+		d->chatState = StateActive;
+	t = root.elementsByTagNameNS(chatStateNS, "composing").item(0).toElement();
+	if(!t.isNull())
+		d->chatState = StateComposing;
+	t = root.elementsByTagNameNS(chatStateNS, "paused").item(0).toElement();
+	if(!t.isNull())
+		d->chatState = StatePaused;
+	t = root.elementsByTagNameNS(chatStateNS, "inactive").item(0).toElement();
+	if(!t.isNull())
+		d->chatState = StateInactive;
+	t = root.elementsByTagNameNS(chatStateNS, "gone").item(0).toElement();
+	if(!t.isNull())
+		d->chatState = StateGone;
+	
+
 	// xencrypted
 	t = root.elementsByTagNameNS("jabber:x:encrypted", "x").item(0).toElement();
 	if(!t.isNull())
@@ -1488,6 +1543,15 @@
 	return test(ns);
 }
 
+#define FID_CHATSTATE "http://jabber.org/protocol/chatstates";
+bool Features::canChatState() const
+{
+	QStringList ns;
+	ns << FID_CHATSTATE;
+
+	return test(ns);
+}
+
 #define FID_VCARD "vcard-temp"
 bool Features::haveVCard() const
 {

Attachment: pgpMFYFEu2rpc.pgp
Description: PGP signature

_______________________________________________
kopete-devel mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/kopete-devel

Reply via email to