README for KIMProxy
Generic instant messaging interface for KDE

Will Stephenson 2004 lists@stevello.free-online.co.uk

This library combines a number of functions needed for arbitrary KDE apps (service users) to make use of IM functions provided by dedicated IM client applications (service providers, in this context).

A generic DCOP interface enables loose coupling, so programs using the library need not know the details of the IM client used for messaging.

WWW

http://homepages.cs.ncl.ac.uk/william.stephenson/home.informal/iface_design_notes.html

Todo

Agree a final interface that suits IM apps, PIM apps, games and other apps needing IM services. (in progress )

Implement this interface on Kopete and library, other KDE IM apps if interested( in progress ).

Provide interface for viewing/editing multiple IM addresses stored in kabc.
( in progress ).

Make our schema for storing multiple IM addresses in KABC compliant with the draft extension to the vcard standard, and thus OSX compatible.

Improve Kopete's IM address writing code

Extend Kopete to write selected IM provided data to KABC.


Architecture

1) Generic DCOP interface allows any service user to use any service provider implementing the interface without having to have provider specific interface code.

2) Service location function allows a service user to discover and communicate with a previously unknown service provider at runtime.

3) New and existing KDE IM Clients become service providers by implementing/extending the generic interface, and register this capability centrally.

4) Users specify their preferred service provider, in case there are >1 apps running that offer the interface.

IPC

The actual 'protocol' for exchange of IM information is just what the Kopete team hashed out at n7y and afterwards, and could be easily changed to meet service users' needs.

	* Service user (eg KRfb) finds service provider (eg Kopete)
	* user queries provider for contact list
	* user queries provider for statuses for some contacts
	* user requests to send some data over IM using provider
	* provider signals user when contacts' status change

	I arbitrarily chose to only deal in contacts that are associated with KABC entries.  I'm probably just exporting Kopete's idea that it's a person you communicate with, not an ICQ number or IRC nick.  It saves apps from thinking about different IM protocols and who's who, and half the need for all this comes from PIM where you're mostly dealing with KABC addressees.  It would be easy to change this though.

	It would also be possible for KABC aware apps to find out about IM contactable contacts from KABC fields, either the one that kaddressbook provides at the moment, or the X-messaging custom fields that Kopete has been using, and send a KABC Uid to the service provider.
	
Implementation

1) I've taken the kopete DCOP interface as a starting point for a KIMIface DCOP interface - now let's find out what everyone wants/needs.

2) KDE ServiceType DCOP/InstantMessenger describes an app providing KIMIface.  Using our KTrader and kio/KDCOPServiceStarter we can get the name of a service provider at runtime.

3) Kopete is patched to offer KIMIface over DCOP instead of KopeteIface.  These are the same at the moment, but if KIMIface shrinks, Kopete can either extend KIMIface or provide an additional interface for compatibility with existing DCOP clients.  kopete.desktop gains a ServiceTypes=DCOP/InstantMessenger line so that service location via KDCOPServiceStarter returns it

4) I've used kcm_componentchooser for users to set their preferred service provider ( out of a choice of Kopete... or Kopete :), and guess what the default is).  KIMProxy reads this preference and uses it when looking for a service provider (but see Bugs below).

Details

	KIMProxy is a helper library that combines service location, wrapping DCOP to ease calling methods on the service provider, and receiving notifications from service providers, which are passed on to the service user as Qt signals.  The aim is to make programmers' lives easier, because although the code is not very complex, we need both a DCOPClient and DCOPObject to perform function calls and receive DCOP signals, and this wraps that complexity.
	
	It contains an IMLabel widget which is a DCOP aware QLabel subclass, to make it easy to use the functionality in other apps - just pass it your KIMProxy instance and a KABC::Addressee.

	IMLabel does the following:
	- gets its tooltip and label (name/status) from KIMIFace 
	- gets a pixmap from KABC (if set) or KIMIFace
	- has context menu for chat, message, file xfer (where supported)
	- accepts file drag and drop

The operations KIMIFace/KIMProxy provide at the moment are:

	initialize() - do your service discovery, discover in advance if there aren't any IM service providers on the system.  Optional because it is called before every real DCOP call in case the running IM clients changed while we were running.
	imAddresseeUids() - get a list of KABC UIDs that the IM client can communicate with (no status information).  Might be a problem if you had a very large contact list all registered in KABC (Casey).

	statusString( uid ) - i18n()ed status string for the given KABC uid
	statusNumeric( uid ) - integer status code for the given KABC uid - see kimproxy.h
	chatContactById( uid ) - start a chat with a KABC uid, interactively.  Probably an noninteractive single shot message would be useful too, since any reply will be picked up by the IM client interactively.

	statusIcon( uid ) - a QPixmap representing the status

	messageContactByID( uid, message ) - ask the client to send the given message
	sendFileToId( uid, file_url ) - perform file transfer

	and a (Qt) signal:

	sigContactStatusChanged( uid ) - uid's online status changed. Should probably include the numeric status code, but since this signal is sent over DCOP for every KABC registered IM contact, I have started small - can anyone tell me if this is really an issue? (see Shortcomings)

	it needs a

	connect() function to tell the service provider to go online.

Bugs/Shortcomings

- Only one service provider in KDE at the moment (Kopete)

- Generic interface header (kimiface.h) isn't installed in $KDEDIR/includes yet,   pending a finished version.

- the DCOP signal connection in KIMProxy only works completely anonymously, not when receiving from an unnamed application but a named object (KIMIface), so we accept signals from any source.

- status notification via DCOP signal is only tacked onto Kopete in completely the wrong place (in the contactlist, not in libkopete) and needs doing properly.

- service location using preferences doesn't work yet and is disabled.  This may be due to the requirement that KTrader preferences expressions return an integer, but I don't know how if my name equality test does this. I'm hoping a DCOP wizard will help out here.

- the location where user's app preferences are stored is hardcoded into KIMProxy.  It's the same as in kcm_instantmessenger.desktop, but it didn't feel right to read this out of $KDEDIR/apps/kcm_componentchooser.  I couldn't find another implementation where this information is obtained at runtime.  Would it be better if kcm_instantmessenger.desktop was combined with the ServiceType spec in dcopinstantmessenger.desktop and kcm_componentchooser just discovered which services it should configure from ServiceTypes?

- IM service providers emit DCOP signals every time a KABC registered contact changes status.  Does this have a cost attached?  It could be avoided by having a 'subscribe' type interface on the service providers so they only signal on contacts other apps are known to be interested, but this would make service providers more complicated, unless maybe DCOP did real pub/sub semantics.

- I am pretty sure that multiple instances of KIMProxy will be safe, can anyone confirm this?

- IMApplet is made out of feathers and spit and is a demo, not for real use (probably leaks memory like mad).

- IMLabel is nearly as bad - it's intended as a sample of what we could do with it and to make it easy for app developers to try it out, not production code.  It could do a better job of dealing with resizes too yet but I am no good at GUIs. Patches welcome!

Files

interfaces/
	kimiface.h
	- Generic DCOP interface definition for IM clients to implement
	dcopinstantmessenger.desktop    
	- KDE ServiceType, specifying a class of IM clients that implement
	  kimiface.h.
	kcm_instantmessenger.desktop
	- config file for kcm_componentchooser so it allows users to specify
	  their preferred IM client
	  
src/
	kimproxy.h
	- Helper library for apps needing IM services to link to
	kimproxy.cpp
	- Definition of above
	kimproxyiface.h
	- Definition of proxy's DCOP interface, needed to allow it to receive
	  DCOP signals
	imlabel.h
	imlabel.cpp
	- Example widget representing an IM contact.
	imbutton.h
	imbutton.cpp
	- Original attempt at the above, just a button with pic and tooltip

applet/
	Proof-of-concept client kicker applet using libkimproxy
	imapplet.h
	- Applet declaration
	imapplet.cpp
	- Applet definition
	imapplet.desktop
	- Applet desktop file so it will be loaded by kicker.

konq_servicemenu/
	Proof-of-concept konqueror service menu entry presenting IM services using KIMIface
	sendViaIM.sh 
	- Shell script to choose a file transfer recipient using dcop and kdialog
	send_via_im.desktop 
	- Specifies the service menu entry
