diff options
Diffstat (limited to 'interfaces/kimproxy')
22 files changed, 2106 insertions, 0 deletions
diff --git a/interfaces/kimproxy/Makefile.am b/interfaces/kimproxy/Makefile.am new file mode 100644 index 000000000..105f84291 --- /dev/null +++ b/interfaces/kimproxy/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = interface library
\ No newline at end of file diff --git a/interfaces/kimproxy/TODO b/interfaces/kimproxy/TODO new file mode 100644 index 000000000..fc66130fe --- /dev/null +++ b/interfaces/kimproxy/TODO @@ -0,0 +1,10 @@ +For the future, the following modifications need to be done: + +Currently there is a function : + virtual QString presenceString( const QString & uid ) = 0; +This needs to be broken into: + virtual QString presenceString( const QString & uid ) = 0; + virtual QString presenceLongString( const QString & uid ) = 0; + +The former returning, say "Away", the latter returning the long away +message. diff --git a/interfaces/kimproxy/interface/Makefile.am b/interfaces/kimproxy/interface/Makefile.am new file mode 100644 index 000000000..348130e46 --- /dev/null +++ b/interfaces/kimproxy/interface/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = $(all_includes) + +kimifaceinclude_HEADERS = kimiface.h +kimifaceincludedir = $(includedir) + +servicetypedir = $(kde_servicetypesdir) +servicetype_DATA = dcopinstantmessenger.desktop + +kcm_instantmessenger_DATA = kcm_instantmessenger.desktop +kcm_instantmessengerdir = $(kde_datadir)/kcm_componentchooser + +include $(top_srcdir)/admin/Doxyfile.am +DOXYGEN_REFERENCES = kabc diff --git a/interfaces/kimproxy/interface/dcopinstantmessenger.desktop b/interfaces/kimproxy/interface/dcopinstantmessenger.desktop new file mode 100644 index 000000000..406c4e979 --- /dev/null +++ b/interfaces/kimproxy/interface/dcopinstantmessenger.desktop @@ -0,0 +1,72 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=DCOP/InstantMessenger +Comment=Instant Messenger with a DCOP interface +Comment[af]=Oombliklike Boodskapper met DCOP intervlak +Comment[be]=Імгненны абвестнік з інтэрфэйсам DCOP +Comment[bg]=Програма за съобщения в реално време с интерфейс DCOP +Comment[bn]=ডিকপ (DCOP) ইন্টারফেস সহ ইনস্ট্যান্ট মেসেঞ্জার +Comment[bs]=Instant poruke sa DCOP interfejsom +Comment[ca]=Missatgeria instantània amb una interfície DCOP +Comment[cs]=Komunikátor s DCOP rozhraním +Comment[csb]=Internetowi kòmùnikator z interfejsã DCOP +Comment[cy]=Negesydd Chwim efo rhyngwyneb DCOP +Comment[da]=Instant Messenger med en DCOP-grænseflade +Comment[de]=Instant Messenger mit DCOP-Schnittstelle +Comment[el]=Στιγμιαίος αποστολέας με διασύνδεση DCOP +Comment[eo]=Tujmesaĝilo kun DCOP-interfaco +Comment[es]=Instant Messenger con un interfaz DCOP +Comment[et]=Kiirsuhtlemisrakendus DCOP-liidesega +Comment[eu]=Berehalako mezularitza DCOP interfazearekin +Comment[fa]=پیامرسان فوری با یک واسط DCOP +Comment[fi]=Pikaviestiohjelma, jossa on DCOP-rajapinta +Comment[fr]=Messagerie instantanée munie d'une interface DCOP +Comment[fy]=Instant Messenger mei in DCOP-interface +Comment[ga]=Clár teachtaireachtaí meandaracha le comhéadan DCOP +Comment[gl]=Mensaxeria Instantánea con interface DCOP +Comment[he]=תכנת מסרים מידיים עם ממשק DCOP +Comment[hi]=डीकॉप इंटरफेस सहित इंस्टैंट मैसेंजर +Comment[hr]=Trenutne poruke s DCOP sučeljem +Comment[hsb]=Instant Messenger z DCOP-interfejsom +Comment[hu]=Azonnali üzenetküldő DCOP-felülettel +Comment[id]=Instant Messenger dengan antarmuka DCOP +Comment[is]=Spjallforrit með DCOP viðmóti +Comment[it]=Messaggistica istantanea con un'interfaccia DCOP +Comment[ja]=DCOP インターフェースをもつインスタントメッセンジャー +Comment[ka]=DCOP ინტერფეისთან შეტყობინებების გაცვლის შიკრიკი +Comment[kk]=DCOP интерфейсті жедел хабарласу бағдарламасы +Comment[km]=កម្មវិធីជជែកកំសាន្តដែលមានចំណុចប្រទាក់ DCOP +Comment[lb]=Instant Messenger mat engem DCOP-Interface +Comment[lt]=Momentinių žinučių klientas su DCOP sąsaja +Comment[mk]=Инстант Гласник (Messenger) со DCOP интерфејс +Comment[ms]=Utusan Segera dengan antaramuka DCOP +Comment[nb]=Lynmeldingsprogram med DCOP-grensesnitt +Comment[nds]=Kortnarichten-Maker mit DCOP-Koppelsteed +Comment[ne]=DCOP इन्टरफेससँग आवश्यक मेसेन्जर +Comment[nl]=Instant messenger met een DCOP interface +Comment[nn]=Lynmeldingsprogram med DCOP-grensesnitt +Comment[pa]=ਇੱਕ DCOP ਇੰਟਰਫੇਸ ਲਈ ਇੱਕ ਮੌਕਾ ਸੁਨੇਹਾਕਾਰ +Comment[pl]=Komunikator internetowy z interfejsem DCOP +Comment[pt]=Mensageiro Instantâneo com interface DCOP +Comment[pt_BR]=Mensageiro Instantâneo com uma interface DCOP +Comment[ro]=Aplicaţie de mesaje instantanee cu interfaţă DCOP +Comment[ru]=Клиент обмена сообщениями с интерфейсом DCOP +Comment[rw]=Intumwa y'Akokanya ifite imigaragarire DCOP +Comment[se]=Šleađgadiehtoprográmma mas lea DCOP-lákta +Comment[sk]=Instant Messanger s rozhraním DCOP +Comment[sl]=Takojšni sporočilnik z vmesnikom DCOP +Comment[sr]=Брзи гласник са DCOP интерфејсом +Comment[sr@Latn]=Brzi glasnik sa DCOP interfejsom +Comment[sv]=Direktmeddelanden med ett DCOP-gränssnitt +Comment[ta]=உடனடி செய்தியாளர் DCOP இடைமுகத்தோடு +Comment[te]=డిసిఓపి ఇంటర్ఫెస్ కలిగివున్న ఇంస్టెంట్ మెస్సెన్జర్ +Comment[tg]=Мубодилаи паёмҳо бо интерфейси DCOP +Comment[th]=โปรแกรมส่งข้อความแบบทันที ด้วยส่วนติดต่อกับ DCOP +Comment[tr]=DCOP arayüzüyle Anında Mesajlaşma +Comment[tt]=DCOP protokolı belän Aşığıç Xäbärçe +Comment[uk]=Програма для миттєвого зв'язку через DCOP +Comment[vi]=Bộ tin nhắn tức khắc có giao diện DCOP +Comment[wa]=Messaedjreye sol moumint avou ene eterface DCOP +Comment[zh_CN]=带 DCOP 接口的即时通讯程序 +Comment[zh_HK]=附有 DCOP 介面的即時通訊軟件 +Comment[zh_TW]=DCOP 介面的即時通訊系統 diff --git a/interfaces/kimproxy/interface/kcm_instantmessenger.desktop b/interfaces/kimproxy/interface/kcm_instantmessenger.desktop new file mode 100644 index 000000000..860f82944 --- /dev/null +++ b/interfaces/kimproxy/interface/kcm_instantmessenger.desktop @@ -0,0 +1,138 @@ +Name=Instant Messenger +Name[af]=Oombliklike Boodskapper +Name[be]=Імгненны абвеснік +Name[bg]=Съобщения в реално време +Name[bn]=ইনস্ট্যান্ট মেসেঞ্জার +Name[br]=Posteler a-benn-kaer +Name[bs]=Instant poruke +Name[ca]=Missatgeria instantània +Name[cs]=Komunikátor +Name[csb]=Internetowi kòmùnikator +Name[cy]=Negesydd Chwim +Name[el]=Στιγμιαίος αποστολέας +Name[eo]=Tujmesaĝilo +Name[et]=Kiirsuhtlus +Name[eu]=Berehalako mezularitza +Name[fa]=پیامرسان فوری +Name[fi]=Pikaviestiohjelma +Name[fr]=Messagerie instantanée +Name[ga]=Clár teachtaireachtaí meandaracha +Name[gl]=Mensaxeria Instantánea +Name[he]=מסרים מידיים +Name[hi]=इंस्टैंट मैसेंजर +Name[hu]=Azonnali üzenetküldő +Name[is]=Spjallforrit +Name[it]=Messaggistica istantanea +Name[ja]=インスタントメッセンジャー +Name[ka]=შიკრიკი +Name[kk]=Жедел хабарласу +Name[km]=កម្មវិធីវិធីជជែកកំសាន្ត +Name[lt]=Momentinių žinučių klientas +Name[mk]=Инстант Гласник (Messenger) +Name[ms]=Mesej Segera +Name[nb]=Lynmelding +Name[nds]=Kortnarichten-Maker +Name[ne]=आवश्यक मेसेन्जर +Name[nl]=Instant messenger +Name[nn]=Lynmelding +Name[pa]=ਮੌਕਾ ਸੁਨੇਹਾਕਾਰ +Name[pl]=Komunikator internetowy +Name[pt]=Mensageiro Instantâneo +Name[pt_BR]=Mensagem Instantâneo +Name[ro]=Mesaje instantanee +Name[ru]=Обмен сообщениями +Name[se]=Šleađgadieđut +Name[sl]=Takojšni sporočilnik +Name[sr]=Брзи гласник +Name[sr@Latn]=Brzi glasnik +Name[sv]=Direktmeddelanden +Name[ta]=உடனடி செய்தியாளர் +Name[te]=ఇంస్టెంట్ మెస్సెన్జర్ +Name[tg]=Мубодилаи паёмҳо +Name[th]=โปรแกรมส่งข้อความทันที +Name[tr]=Anında Mesajlaşma +Name[tt]=Aşığıç Xäbärçe +Name[uk]=Програма для миттєвого зв'язку через DCOP +Name[uz]=Xabar almashish vositasi +Name[uz@cyrillic]=Хабар алмашиш воситаси +Name[vi]=Bộ tin nhắn tức khắc +Name[wa]=Messaedjreye sol moumint +Name[zh_CN]=即时通讯程序 +Name[zh_HK]=即時通訊軟件 +Name[zh_TW]=即時通訊 +Comment=The instant messenger allows two-way chat between individuals and groups. +Comment[af]=Die oombliklike boodskappe laat twee rigting kommunikasie tussen individue en groepe toe. +Comment[be]=Імгненны абвеснік дазваляе весці размову двум і больш асобам/гуртам. +Comment[bg]=Разговор между различни хора в реално време. +Comment[bn]=ইনস্ট্যান্ট মেসেঞ্জার একাধিক ব্যক্তি বা গোষ্ঠীকে দ্বিমুখী বার্তালাপ বা আড্ডার সুযোগ দেয়। +Comment[bs]=Program za instant poruke omogućuje dvosmjernu komunikaciju između pojedinaca i grupa. +Comment[ca]=La missatgeria instantània permet converses en dos sentits entre individus i grups. +Comment[cs]=Komunikátor vám umožňuje obousměrný rozhovor s jednotlivci nebo skupinami. +Comment[csb]=Internetowi kòmùnikator dôwô mòżnota kôrbionczi midzë lëdzama ë karnama. +Comment[cy]=Mae'r negesydd chwim yn caniatàu sgwrs dwy-ffordd rhwng unigolion a grwpiau. +Comment[da]=Instant messenger tillader tovejs chat mellem individer og grupper. +Comment[de]=Der Instant Messenger ermöglicht Chats zwischen Personen und Gruppen in jede Richtung. +Comment[el]=Ο στιγμιαίος αποστολέας επιτρέπει τη συζήτηση μεταξύ ατόμων και ομάδων. +Comment[eo]=La tujmesaĝilo ebligas ambaŭdirekta parolado inter homoj kaj grupoj +Comment[es]=El Instant Messenger permite conversación en dos sentidos entre indivíduos y grupos. +Comment[et]=Kiirsuhtlus võimaldab üksikisikute ja gruppide kahepoolset vestlust. +Comment[eu]=Berehalako mezularitzak banan-banako edo taldeen arteko berriketan aritzeko. +Comment[fa]=پیامرسان فوری امکان گپ دو طرفه بین افراد و گروهها را میدهد. +Comment[fi]=Pikaviestiohjelman avulla voidaan keskustella kahden kesken tai ryhmässä. +Comment[fr]=La messagerie instantanée permet un dialogue bidirectionnel entre individus et groupes. +Comment[fy]=Mei de instant messenger kinne jo twaspraak hâlde mei in yndividu en groepen. +Comment[ga]=Is féidir comhrá déthreoch a dhéanamh idir daoine agus grúpaí leis an gclár teachtaireachtaí meandaracha. +Comment[gl]=O instant messenger permite conversas nos dous sentidos entre indivíduos e grupos. +Comment[he]=תוכנת מסרים מידיים מאשרת לשוחח ברשת (לצ'טט) בין יחידים או קבוצות +Comment[hi]=इंस्टैंट मैसेंजर जो व्यक्तियों या समूहों के बीच दो-तरफा गपशप स्वीकारता है. +Comment[hr]=Trenutne poruke omogućuju dvosmjerno brbljanje između pojedinaca i grupa. +Comment[hsb]=Instant messenger zmóžni jednotliwcam a skupinam spěšnu wuměnu zdźělenkow. +Comment[hu]=Interaktív társalgást tesz lehetővé az interneten keresztül két személy vagy csoport között. +Comment[id]=Instant messenger memungkinan chat dua-arah antara individu dan grup +Comment[is]=Spjallforritið gerir einstaklingum og hópum kleyft að spjalla saman á einfaldan máta. +Comment[it]=La messaggistica istantanea permette di chiacchierare tra due persone o in gruppo. +Comment[ja]=インスタントメッセンジャーは個人とグループとの双方向チャットを可能にします。 +Comment[ka]=შიკრიკი პიროვნებებსა და ჯგუფებს შორის მყისი შეტყობინებების გაცვლის საშუალებას იძლევა. +Comment[kk]=Жедел хабарласу жеке тұлға және топтар араларында әңгімелесу мүмкіндігін береді. +Comment[km]=កម្មវិធីជជែកកំសាន្តអនុញ្ញាតឲ្យជជែកតាមរបៀបពីរបែបរវាងបុគ្គល និងក្រុម ។ +Comment[lb]=Den Instant Messenger erlaabt eng zwee-Weeër Kommunikatioun tëschent eenzelne Persounen a Gruppen. +Comment[lt]=Momentinių žinučių klientas kalbėtis individams ir grupėms. +Comment[mk]=Инстант гласникот овозможува двонасочна комуникација меѓу индивидуи и групи. +Comment[ms]=Utusan segera membenarkan perbualan di antara individu dan kumpulan. +Comment[nb]=Et lynmeldingsprogram som tallater toveis samtale mellom enkeltpersoner og grupper. +Comment[nds]=Mit den Kortnarichten-Maker köönt enkelte Minschen oder Gruppen ünnerenanner snacken. +Comment[ne]= आवश्यक मेसेन्जरले एकल र समूहहरुबीच दोहोरो कुराकानीलाई अनुमति दिन्छ । +Comment[nl]=De instant messenger maakt directe communicatie tussen personen of groepen mogelijk. +Comment[nn]=Eit lynmeldingsprogram som tillèt tovegsprat mellom enkeltpersonar og grupper. +Comment[pa]=ਇਹ ਮੌਕਾ ਸੁਨੇਹਾਕਾਰ ਇੱਕਲੇ ਤੇ ਸਮੂਹ ਵਿਚਕਾਰ ਦੋ ਪਾਸੀ ਗਲਬਾਤ ਲਈ ਸਹਾਇਕ ਹੈ +Comment[pl]=Komunikator internetowy umożliwia pogawędki między dwiema osobami lub grupami osób. +Comment[pt]=O mensageiro instantâneo permite conversar entre dois extremos com indivíduos e com grupos. +Comment[pt_BR]=O mensageiro instantâneo permite que exista um bate-papo entre indivíduos e grupos +Comment[ro]=Aplicaţia de mesaje instantanee permite convorbiri între persoane sau grupuri de persoane. +Comment[ru]=Клиент обмена сообщениями служит для обмена сообщениями между людьми и группами. +Comment[rw]=Intumwa y'Akokanya yemerera inzira-zombi z'ikiganiroInterineti hagati y'abantu ubwabo n'amatsinda +Comment[se]=Šleađgadiehtoprográmma gos olbmot ja joavkkut sáhttet buillardallat (chat). +Comment[sk]=Instant messenger umožňuje rozhovor medzi rôznymi osobami a skupinami. +Comment[sl]=Takojšni sporočilnik omogoča dvosmeren klepet med posamezniki in skupinami. +Comment[sr]=Брзи гласник вам омогућава двосмерно ћаскање између појединаца и група. +Comment[sr@Latn]=Brzi glasnik vam omogućava dvosmerno ćaskanje između pojedinaca i grupa. +Comment[sv]=Direktmeddelanden möjliggör tvåvägschatt mellan individer och grupper. +Comment[ta]=உடனடி தகவல் உங்களை இரண்டு வழியில் தனிநபர் மற்றும் குழுக்கள் இடையே அனுமதிக்கும். +Comment[te]=ఇంస్టెంట్ మెస్సెన్జర్ వ్యక్తు లు మరయు గుంపుల తొ ఇరువయపుల నుంచి సంబాషించవచ్చు +Comment[tg]=Мубодилаи паёмҳо барои сӯҳбат бо шахсони ҷудогона ва гурӯҳӣ иҷозат медиҳад. +Comment[th]=โปรแกรมส่งข้อความแบบทันที จะอนุญาตให้มีการพูดคุยสองทาง ทั้งระหว่าง บุคคลและกลุ่ม +Comment[tr]=Anında mesajlaştırıcı iki yollu sohbet sağlar: bireyler ve gruplar. +Comment[tt]=Bu aşığıç xäbärçe aşa keşe-törkemnär arasında ike-yaqlı aralaşu mömkinlegen birä. +Comment[uk]=Програма для миттєвого зв'язку дозволяє розмовляти з іншою людиною чи групою людей. +Comment[vi]=Bộ tin nhắn tức khắc cho phép trò chuyện hai chiều giữa người riêng và nhóm. +Comment[wa]=Li messaedjreye sol moumint permete di berdeler dins les deus sinses etur deus djins ou e groupe. +Comment[zh_CN]=允许在个人和群组之间双向聊天的即时通讯程序。 +Comment[zh_HK]=即時通訊軟件可以讓用戶和別的用戶或羣組通訊。 +Comment[zh_TW]=即時通訊系統允許兩個人或兩個群組間的聊天與對話 +ServiceTypeToConfigure=DCOP/InstantMessenger +MimeTypeOfInterest=DCOP/InstantMessenger +defaultImplementation=kopete +storeInFile=default_components +valueSection=InstantMessenger +valueName=imClient +configurationType=component diff --git a/interfaces/kimproxy/interface/kimiface.h b/interfaces/kimproxy/interface/kimiface.h new file mode 100644 index 000000000..4cc1d88b5 --- /dev/null +++ b/interfaces/kimproxy/interface/kimiface.h @@ -0,0 +1,500 @@ +/* + kimiface.h - KDE Instant Messenger DCOP Interface + + Copyright (c) 2004-5 Will Stephenson <lists@stevello.free-online.co.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KIMIFACE_H +#define KIMIFACE_H + +#include <qpixmap.h> +#include <dcopobject.h> +#include <qstringlist.h> +#include <kurl.h> + +/** + * @brief Generic DCOP interface for KDE instant messenger applications + * + * The interface has two parts: + * - methods to get information about IM-contacts, such as their reachability + * or their presence status (if the are online or away, etc) + * - methods to initiate communication with IM-contacts, e.g. sending messages + * + * @note If you are looking for a information about accessing application's + * that implement this interface, have a look at the KIMProxy class. + * + * Contacts are identified using unique identifier strings (UID) used by + * KABC, the KDE address book library. + * The UID generation is handled by KABC::Addressee so the your application + * will either have to access the address book or provide a possibility + * for associating a contact of your application with an entry of the address + * book. + * + * @note one omission of this interface is the lack of control over the range + * of values used for protocols' names. + * + * If you are implementing this interface, note that your application must + * have the following information in its desktop file, so that it can be + * identified as providing KIMIface at runtime: + * @code + * X-DCOP-ServiceName=<application-name> + * ServiceTypes=DCOP/InstantMessenger + * @endcode + * and the class implementing KIMIface must pass "KIMIface" to the DCOPObject constructor: + * @code + * // just need QObject inheritance and Q_OBJECT if you want signals and slots + * // no need to use K_DCOP macro again + * + * class MyIMIface : public QObject, public KIMIface + * { + * Q_OBJECT + * public: + * MyIMIface(QObject* parent = 0, const char* name) : + * DCOPObject("KIMIface"), // <-- passing the interface name as required + * QObject(parent, name) {} + * }; + * @endcode + * + * The DCOP part of the interface needs to be processed by the DCOP IDL + * compiler. The KDE autotools framework will do this automatically, all + * you have to do is add kimiface.skel and kimiface.stub to the + * @c SOURCES list in your @c Makefile.am + * + * @see KIMProxy + * @see KABC::AddressBook + * @see KABC::Addressee + * + * @since 3.3 + * @author Will Stephenson <lists@stevello.free-online.co.uk> + */ +class KIMIface : virtual public DCOPObject +{ + K_DCOP + +k_dcop: +// ACCESSORS +// contact list + /** + * @brief Obtain a list of IM-contacts that are known to the application + * + * Return a list of KABC UIDs of all the contacts you have such IDs for. + * + * @return a list of KABC UIDs known to the application + * + * @see reachableContacts() + * @see onlineContacts() + * @see fileTransferContacts() + * @see isPresent() + * @see KABC::Addressee::uid() + */ + virtual QStringList allContacts() = 0; + + /** + * @brief Obtain a list of IM-contacts that are currently reachable + * + * Return a list of KABC UIDs of the contacts that are reachable in the + * sense that you are connected to the IM-service they are + * associated with. + * + * For example if your application supports ICQ and AIM and the ICQ account is + * active but the AIM account isn't, return just the ICQ contacts. + * + * @return a list of KABC UIDs who can receive a message, even if offline + * + * @see allContacts() + * @see onlineContacts() + * @see fileTransferContacts() + * @see messageContact() + * @see KABC::Addressee::uid() + */ + virtual QStringList reachableContacts() = 0; + + /** + * @brief Obtain a list of IM-contacts that are currently online + * + * Return a list of KABC UIDs of the contacts you have any presence + * information for that indicates that they are connected to the + * IM-service they are associated with. + * + * @return a list of KABC UIDs who are online with unspecified presence + * + * @see allContacts() + * @see reachableContacts() + * @see fileTransferContacts() + * @see messageContact() + * @see chatWithContact() + * @see KABC::Addressee::uid() + */ + virtual QStringList onlineContacts() = 0; + + /** + * @brief Obtain a list of IM-contacts who may receive file transfers + * + * Return a list of KABC UIDs of the contacts that are capable of + * receiving file transfers based on the IM-service they are associated + * with, i.e. if it is technically able to provide this, on their online + * state, i.e. can likely not receive files while offline, and perhaps even + * information your application has additionally, e.g. a user config that + * tells you that the contact is behind a firewall. + * + * The simplest implementation is to return the same list as + * onlineContacts(), provided all the IM-services that are currently used + * support it. + * + * @return a list of KABC UIDs capable of file transfer + * + * @see allContacts() + * @see reachableContacts() + * @see onlineContacts() + * @see canReceiveFiles() + * @see sendFile() + * @see KABC::Addressee::uid() + */ + virtual QStringList fileTransferContacts() = 0; + +// individual + /** + * @brief Confirm if a given contact is known to the IM application + * + * Check if you can map the given KABC UID to one if the IM-contacts, e.g. + * the would be part of the list returned by allContacts() + * + * @param uid the KABC UID you are interested in + * @return whether the program knows of this KABC UID + * + * @see allContacts() + * @see presenceString() + * @see presenceStatus() + * @see KABC::Addressee::uid() + */ + virtual bool isPresent( const QString & uid ) = 0; + + /** + * @brief Obtain the IM app's idea of the contact's display name + * + * Useful if KABC lookups may be too slow. Should return whatever + * the application uses in its contact list or similar GUI, e.g. + * a nick name, a user configured name string, etc. + * + * @param uid the KABC UID you are interested in + * @return the corresponding display name or QString:null if the + * UID is unknown + * + * @see isPresent() + * @see presenceString() + * @see presenceStatus() + * @see KABC::Addressee::uid() + */ + virtual QString displayName( const QString & uid ) = 0; + + /** + * @brief Obtain the IM presence as a i18ned string for the specified + * contact + * + * Return a translated string your application would use when displaying + * the contact's presence, e.g. i18n("Online"), i18n("Away") + * + * @param uid the KABC UID you want the presence for + * @return the i18ned string describing the contact's presence or + * QString::null if the UID is unknown + * + * @see isPresent() + * @see presenceStatus() + * @see KABC::Addressee::uid() + */ + virtual QString presenceString( const QString & uid ) = 0; + + /** + * @brief Obtain the IM presence as a number for the specified contact + * + * Return one of the following values depending on the given contact's + * presence: + * - 0 - @c Unknown: for contacts where you can not use any of the other + * values + * + * - 1 - @c Offline: for contacts that are offline, i.e. not connected to + * their IM-service. If the application itself or the IM-service for the + * given contact is offline return @c Unknown instead + * + * - 2 - @c Connecting + * + * - 3 - @c Away: for contacts that are connected to their IM-service but + * not @c Online + * + * - 4 - @c Online + * + * @param uid the KABC UID you want the presence for + * @return a numeric representation of presence - currently one of + * 0 (Unknown), 1 (Offline), 2 (Connecting), 3 (Away), 4 (Online). + * Returns 0 if the given UID is unknown + * + * @see isPresent() + * @see presenceString() + * @see KABC::Addressee::uid() + */ + virtual int presenceStatus( const QString & uid ) = 0; + + /** + * @brief Indicate if a given contact can receive files + * + * @param uid the KABC UID you want to the file transfer capability for + * @return whether the specified contact can receive files + * + * @see fileTransferContacts() + * @see KABC::Addressee::uid() + */ + virtual bool canReceiveFiles( const QString & uid ) = 0; + + /** + * @brief Indicate if a given contact will be able to respond + * + * Some media are unidirectional (e.g., sending SMS via a web interface). + * This refers to the contact's ability to respond as defined by the + * medium, not by their presence. + * + * Someone may appear offline (SMS has no presence) to you but in fact be + * able to respond. + * + * @param uid the KABC UID you are interested in + * @return whether the specified contact can respond + * + * @see isPresent() + * @see KABC::Addressee::uid() + */ + virtual bool canRespond( const QString & uid ) = 0; + + /** + * @brief Obtain the KABC UID corresponding to the given IM address + * + * @param contactId the protocol specific identifier for the contact, + * e.g. UIN for ICQ, screenname for AIM, nick for IRC + * @param protocol the IM protocol/service to check. See protocols() + * @return the KABC UID for the given contact or @c QString::null if not + * found or either input stream was empty or the protocol is not + * supported + * + * @see protocols() + * @see addContact() + * @see isPresent() + * @see KABC::Addressee::uid() + */ + virtual QString locate( const QString & contactId, const QString & protocol ) = 0; + +// metadata + /** + * @brief Obtain the icon representing the IM presence for the specified + * contact + * + * Return the image the application would use to display a contact's presence. + * The size and other properties of the image are currently unspecified. + * + * @param uid the KABC UID you want the presence icon for + * @return a pixmap representing the contact's presence or a null pixmap + * if the contact is unknown. See QPixmap::isNull() + * + * @see isPresent() + * @see presenceString() + * @see presenceStatus() + * @see KABC::Addressee::uid() + */ + virtual QPixmap icon( const QString & uid ) = 0; + + /** + * @brief Obtain the given contact's current context (home, work, or any) + * + * Not all IM services/protocols support the concept of contexts. If the + * given UID maps to such a service, just return @c QString::null + * + * @param uid the KABC UID you want the context for + * @return a string describing the context, or @c QString::null if not + * supported or if the contact is unknown + * + * @see isPresent() + * @see KABC::Addressee::uid() + */ + virtual QString context( const QString & uid ) = 0; + +// App capabilities + /** + * @brief Obtain a list of supported IM services/protocols + * + * Protocol names are currently of the form "protocol name" + "Protocol" + * for example: + * - AIMProtocol: AOL instant messenger protocol + * - MSNProtocol: Microsoft messanger protocol + * - ICQProtocol: AOL (Mirabilis) ICQ protocol + * - .... + * + * The string is currently just an identifier to use with methods such as + * locate(), addContact() or messageNewContact() + * + * @return the set of protocols that the application supports + * + * @see locate() + * @see addContact() + * @see messageNewContact + */ + virtual QStringList protocols() = 0; + +// ACTORS + /** + * @brief Send a single message to the specified contact + * + * Any response will be handled by the IM client as a normal + * conversation. + * + * Implementations might send the message silently, ask the user for + * permission or just prefill the usual message input GUI. + * + * @note As sending any text could potentially be a breach of the user's + * privacy it is recommended to let the user know about it. + * + * @param uid the KABC UID you want to send the message to + * @param message the message text to send to the contact + * + * @see messageNewContact() + * @see chatWithContact() + * @see sendFile() + * @see isPresent() + * @see reachableContacts() + * @see KABC::Addressee::uid() + */ + virtual void messageContact( const QString &uid, const QString& message ) = 0; + + /** + * @brief Send a single message to a contact given only its protocol + * specific identifier + * + * This could be used to send a message without having to know the KABC UID + * of the contact or without having to add it first. + * + * @param contactId the protocol specific identifier for the contact, + * e.g. UIN for ICQ, screenname for AIM, nick for IRC + * @param protocol the IM protocol/service to check. See protocols() + * + * @see messageContact() + * @see chatWithContact() + * @see sendFile() + * @see locate() + * @see protocols() + * @see addContact() + */ + virtual void messageNewContact( const QString &contactId, const QString &protocol ) = 0; + + /** + * @brief Start a chat session with the specified contact + * + * Applications that do not support a chat mode or when the IM-service + * of the given contact does not support it, this can also open + * a normal message input GUI. + * + * @param uid the KABC UID you want to chat with + * + * @see messageContact() + * @see messageNewContact() + * @see sendFile() + * @see isPresent() + * @see reachableContacts() + * @see KABC::Addressee::uid() + */ + virtual void chatWithContact( const QString &uid ) = 0; + + /** + * @brief Send a file to the contact + * + * Initiates a file transfer with the given contact if possible. + * + * Implementations might start the transfer right away, ask the user's + * permission or just prefill the usual file transfer GUI. + * + * @note As sending any file could potentially be a breach of the user's + * privacy it is recommended to let the user know about it. + * + * @param uid the KABC UID you want to send to + * @param sourceURL a KURL pointing to the file to send + * @param altFileName an alternate filename describing the file or a + * description or title + * @param fileSize file size in bytes + * + * @see messageContact() + * @see messageNewContact() + * @see chatWithContact() + * @see isPresent() + * @see fileTransferContacts() + * @see KABC::Addressee::uid() + */ + virtual void sendFile(const QString &uid, const KURL &sourceURL, + const QString &altFileName = QString::null, uint fileSize = 0) = 0; + +// MUTATORS +// Contact list + /** + * @brief Add a new contact given its protocol specific identifier + * + * Implementations might add the contact silently, including sending an + * authorization request if necessary, ask the user for confirmation or + * just prefill the usual contact addingGUI. + * + * @param contactId the protocol specific identifier for the contact + * e.g. UIN for ICQ, screenname for AIM, nick for IRC + * @param protocol the IM protocol/service to use. See protocols() + * @return whether the add succeeded. @c false may signal already present, + * protocol not supported, or add operation not supported. + * + * @see locate() + * @see protocols() + * @see messageNewContact() + */ + virtual bool addContact( const QString &contactId, const QString &protocol ) = 0; + +// SIGNALS +k_dcop_signals: + /** + * @brief Indicates that a contact's presence has changed + * + * Notifies connected DCOP receivers about a change in a contact's + * presence. + * + * Implementations just have to call this method with the appropriate + * values to get the DCOP signal emitted. + * + * @param uid the KABC UID whose presence changed + * @param appId the DCOP application ID of the program the signal + * originates from + * @param presence the new presence's numeric value. See presenceStatus() + * + * @see presenceStatus() + * @see KABC::Addressee::uid() + * @see DCOPClient::appId() + */ + void contactPresenceChanged( QString uid, QCString appId, int presence ); +}; + +#endif + + + +/* + * Local variables: + * c-indentation-style: k&r + * c-basic-offset: 8 + * indent-tabs-mode: t + * End: + */ +// vim: set noet ts=4 sts=4 sw=4: + diff --git a/interfaces/kimproxy/library/Makefile.am b/interfaces/kimproxy/library/Makefile.am new file mode 100644 index 000000000..36cb7ea30 --- /dev/null +++ b/interfaces/kimproxy/library/Makefile.am @@ -0,0 +1,26 @@ +SUBDIRS = icons + +INCLUDES = $(all_includes) + +noinst_HEADERS = kimproxyiface.h + +METASOURCES = AUTO + +AM_CPPFLAGS = $(all_includes) + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kimproxy.pot + +kimproxyincludedir = $(includedir) +kimproxyinclude_HEADERS = kimproxy.h kimproxyiface.h + +lib_LTLIBRARIES = libkimproxy.la +libkimproxy_la_LDFLAGS = -no-undefined $(all_libraries) +libkimproxy_la_LIBADD = $(LIB_KIO) +libkimproxy_la_SOURCES = kimproxy.cpp kimiface.stub kimproxyiface.skel + +kimiface_DIR = $(top_srcdir)/interfaces/kimproxy/interface + +include $(top_srcdir)/admin/Doxyfile.am +DOXYGEN_REFERENCES = kabc dcop + diff --git a/interfaces/kimproxy/library/icons/Makefile.am b/interfaces/kimproxy/library/icons/Makefile.am new file mode 100644 index 000000000..a4b97f06a --- /dev/null +++ b/interfaces/kimproxy/library/icons/Makefile.am @@ -0,0 +1 @@ +KDE_ICON=AUTO diff --git a/interfaces/kimproxy/library/icons/cr16-action-presence_away.png b/interfaces/kimproxy/library/icons/cr16-action-presence_away.png Binary files differnew file mode 100644 index 000000000..f96a9c65f --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr16-action-presence_away.png diff --git a/interfaces/kimproxy/library/icons/cr16-action-presence_offline.png b/interfaces/kimproxy/library/icons/cr16-action-presence_offline.png Binary files differnew file mode 100644 index 000000000..f5c53d711 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr16-action-presence_offline.png diff --git a/interfaces/kimproxy/library/icons/cr16-action-presence_online.png b/interfaces/kimproxy/library/icons/cr16-action-presence_online.png Binary files differnew file mode 100644 index 000000000..6cb52496b --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr16-action-presence_online.png diff --git a/interfaces/kimproxy/library/icons/cr16-action-presence_unknown.png b/interfaces/kimproxy/library/icons/cr16-action-presence_unknown.png Binary files differnew file mode 100644 index 000000000..290bc852a --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr16-action-presence_unknown.png diff --git a/interfaces/kimproxy/library/icons/cr32-action-presence_away.png b/interfaces/kimproxy/library/icons/cr32-action-presence_away.png Binary files differnew file mode 100644 index 000000000..086184582 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr32-action-presence_away.png diff --git a/interfaces/kimproxy/library/icons/cr32-action-presence_offline.png b/interfaces/kimproxy/library/icons/cr32-action-presence_offline.png Binary files differnew file mode 100644 index 000000000..caadb14d4 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr32-action-presence_offline.png diff --git a/interfaces/kimproxy/library/icons/cr32-action-presence_online.png b/interfaces/kimproxy/library/icons/cr32-action-presence_online.png Binary files differnew file mode 100644 index 000000000..41e79ad9d --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr32-action-presence_online.png diff --git a/interfaces/kimproxy/library/icons/cr32-action-presence_unknown.png b/interfaces/kimproxy/library/icons/cr32-action-presence_unknown.png Binary files differnew file mode 100644 index 000000000..52ab79ed5 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr32-action-presence_unknown.png diff --git a/interfaces/kimproxy/library/icons/cr48-action-presence_away.png b/interfaces/kimproxy/library/icons/cr48-action-presence_away.png Binary files differnew file mode 100644 index 000000000..58e62c1d3 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr48-action-presence_away.png diff --git a/interfaces/kimproxy/library/icons/cr48-action-presence_offline.png b/interfaces/kimproxy/library/icons/cr48-action-presence_offline.png Binary files differnew file mode 100644 index 000000000..b69630f33 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr48-action-presence_offline.png diff --git a/interfaces/kimproxy/library/icons/cr48-action-presence_online.png b/interfaces/kimproxy/library/icons/cr48-action-presence_online.png Binary files differnew file mode 100644 index 000000000..52fdad8f9 --- /dev/null +++ b/interfaces/kimproxy/library/icons/cr48-action-presence_online.png diff --git a/interfaces/kimproxy/library/kimproxy.cpp b/interfaces/kimproxy/library/kimproxy.cpp new file mode 100644 index 000000000..746c6da90 --- /dev/null +++ b/interfaces/kimproxy/library/kimproxy.cpp @@ -0,0 +1,653 @@ +/* + kimproxy.cpp + + IM service library for KDE + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qglobal.h> +#include <qpixmapcache.h> +#include <dcopclient.h> +#include <kapplication.h> +#include <kdcopservicestarter.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <ksimpleconfig.h> +#include <kiconloader.h> +#include <kservice.h> +#include <kservicetype.h> + +#include "kimiface_stub.h" + +#include "kimproxy.h" + +static KStaticDeleter<KIMProxy> _staticDeleter; + +KIMProxy * KIMProxy::s_instance = 0L; + +struct AppPresenceCurrent +{ + QCString appId; + int presence; +}; + +class ContactPresenceListCurrent : public QValueList<AppPresenceCurrent> +{ + public: + // return value indicates if the supplied parameter was better than any existing presence + bool update( const AppPresenceCurrent ); + AppPresenceCurrent best(); +}; + + +struct KIMProxy::Private +{ + DCOPClient * dc; + // list of the strings in use by KIMIface + QStringList presence_strings; + // list of the icon names in use by KIMIface + QStringList presence_icons; + // map of presences + PresenceStringMap presence_map; +}; + +bool ContactPresenceListCurrent::update( AppPresenceCurrent ap ) +{ + if ( isEmpty() ) + { + append( ap ); + return true; + } + + bool bestChanged = false; + AppPresenceCurrent best; + best.presence = -1; + ContactPresenceListCurrent::iterator it = begin(); + const ContactPresenceListCurrent::iterator itEnd = end(); + ContactPresenceListCurrent::iterator existing = itEnd; + + while ( it != itEnd ) + { + if ( (*it).presence > best.presence ) + best = (*it); + if ( (*it).appId == ap.appId ) + existing = it; + ++it; + } + + if ( ap.presence > best.presence || + best.appId == ap.appId ) + bestChanged = true; + + if ( existing != itEnd ) + { + remove( existing ); + append( ap ); + } + return bestChanged; +} + +AppPresenceCurrent ContactPresenceListCurrent::best() +{ + AppPresenceCurrent best; + best.presence = -1; + ContactPresenceListCurrent::iterator it = begin(); + const ContactPresenceListCurrent::iterator itEnd = end(); + while ( it != itEnd ) + { + if ( (*it).presence > best.presence ) + best = (*it); + ++it; + } + // if it's still -1 here, we have no presence data, so we return Unknown + if ( best.presence == -1 ) + best.presence = 0; + return best; +} + +// int bestPresence( AppPresence* ap ) +// { +// Q_ASSERT( ap ); +// AppPresence::const_iterator it; +// it = ap->begin(); +// int best = 0; // unknown +// if ( it != ap->end() ) +// { +// best = it.data(); +// ++it; +// for ( ; it != ap->end(); ++it ) +// { +// if ( it.data() > best ) +// best = it.data(); +// } +// } +// return best; +// } +// +// QCString bestAppId( AppPresence* ap ) +// { +// Q_ASSERT( ap ); +// AppPresence::const_iterator it; +// QCString bestAppId; +// it = ap->begin(); +// if ( it != ap->end() ) +// { +// int best = it.data(); +// bestAppId = it.key(); +// ++it; +// for ( ; it != ap->end(); ++it ) +// { +// if ( it.data() > best ) +// { +// best = it.data(); +// bestAppId = it.key(); +// } +// } +// } +// return bestAppId; +// } + +KIMProxy * KIMProxy::instance( DCOPClient * client ) +{ + if ( client ) + { + if ( !s_instance ) + _staticDeleter.setObject( s_instance, new KIMProxy( client ) ); + return s_instance; + } + else + return 0L; +} + +KIMProxy::KIMProxy( DCOPClient* dc ) : DCOPObject( "KIMProxyIface" ), QObject(), d( new Private ) +{ + m_im_client_stubs.setAutoDelete( true ); + + d->dc = dc; + m_initialized = false; + connect( d->dc, SIGNAL( applicationRemoved( const QCString& ) ) , this, SLOT( unregisteredFromDCOP( const QCString& ) ) ); + connect( d->dc, SIGNAL( applicationRegistered( const QCString& ) ) , this, SLOT( registeredToDCOP( const QCString& ) ) ); + d->dc->setNotifications( true ); + + d->presence_strings.append( "Unknown" ); + d->presence_strings.append( "Offline" ); + d->presence_strings.append( "Connecting" ); + d->presence_strings.append( "Away" ); + d->presence_strings.append( "Online" ); + + d->presence_icons.append( "presence_unknown" ); + d->presence_icons.append( "presence_offline" ); + d->presence_icons.append( "presence_connecting" ); + d->presence_icons.append( "presence_away" ); + d->presence_icons.append( "presence_online" ); + + //QCString senderApp = "Kopete"; + //QCString senderObjectId = "KIMIface"; + QCString method = "contactPresenceChanged( QString, QCString, int )"; + //QCString receiverObjectId = "KIMProxyIface"; + + // FIXME: make this work when the sender object id is set to KIMIFace + if ( !connectDCOPSignal( 0, 0, method, method, false ) ) + KMessageBox::information( 0, QString( "Couldn't connect DCOP signal.\nWon't receive any status notifications!" ) ); +} + +KIMProxy::~KIMProxy( ) +{ + //d->dc->setNotifications( false ); +} + +bool KIMProxy::initialize() +{ + if ( !m_initialized ) + { + m_initialized = true; // we should only do this once, as registeredToDCOP() will catch any new starts + // So there is no error from a failed query when using kdelibs 3.2, which don't have this servicetype + if ( KServiceType::serviceType( IM_SERVICE_TYPE ) ) + { + //kdDebug( 790 ) << k_funcinfo << endl; + QCString dcopObjectId = "KIMIface"; + + // see what apps implementing our service type are out there + KService::List offers = KServiceType::offers( IM_SERVICE_TYPE ); + KService::List::iterator offer; + typedef QValueList<QCString> QCStringList; + QCStringList registeredApps = d->dc->registeredApplications(); + QCStringList::iterator app; + const QCStringList::iterator end = registeredApps.end(); + // for each registered app + for ( app = registeredApps.begin(); app != end; ++app ) + { + //kdDebug( 790 ) << " considering: " << *app << endl; + //for each offer + for ( offer = offers.begin(); offer != offers.end(); ++offer ) + { + QCString dcopService = (*offer)->property("X-DCOP-ServiceName").toString().latin1(); + if ( !dcopService.isEmpty() ) + { + //kdDebug( 790 ) << " is it: " << dcopService << "?" << endl; + // get the application name ( minus any process ID ) + QCString instanceName = (*app).left( dcopService.length() ); + // if the application implements the dcop service, add it + if ( instanceName == dcopService ) + { + m_apps_available = true; + //kdDebug( 790 ) << " app name: " << (*offer)->name() << ", has instance " << *app << ", dcopService: " << dcopService << endl; + if ( !m_im_client_stubs.find( dcopService ) ) + { + kdDebug( 790 ) << "App " << *app << ", dcopObjectId " << dcopObjectId << " found, using it for presence info." << endl; + m_im_client_stubs.insert( *app, new KIMIface_stub( d->dc, *app, dcopObjectId ) ); + pollApp( *app ); + } + } + } + } + } + } + } + return !m_im_client_stubs.isEmpty(); +} + +void KIMProxy::registeredToDCOP( const QCString& appId ) +{ + //kdDebug( 790 ) << k_funcinfo << " appId '" << appId << "'" << endl; + // check that appId implements our service + // if the appId ends with a number, i.e. a pid like in foobar-12345, + if ( appId.isEmpty() ) + return; + + bool newApp = false; + // get an up to date list of offers in case a new app was installed + // and check each of the offers that implement the service type we're looking for, + // to see if any of them are the app that just registered + const KService::List offers = KServiceType::offers( IM_SERVICE_TYPE ); + KService::List::const_iterator it; + for ( it = offers.begin(); it != offers.end(); ++it ) + { + QCString dcopObjectId = "KIMIface"; + QCString dcopService = (*it)->property("X-DCOP-ServiceName").toString().latin1(); + if ( appId.left( dcopService.length() ) == dcopService ) + { + // if it's not already known, insert it + if ( !m_im_client_stubs.find( appId ) ) + { + newApp = true; + kdDebug( 790 ) << "App: " << appId << ", dcopService: " << dcopService << " started, using it for presence info."<< endl; + m_im_client_stubs.insert( appId, new KIMIface_stub( d->dc, appId, dcopObjectId ) ); + } + } + //else + // kdDebug( 790 ) << "App doesn't implement our ServiceType" << endl; + } + //if ( newApp ) + // emit sigPresenceInfoExpired(); +} + +void KIMProxy::unregisteredFromDCOP( const QCString& appId ) +{ + //kdDebug( 790 ) << k_funcinfo << appId << endl; + if ( m_im_client_stubs.find( appId ) ) + { + kdDebug( 790 ) << appId << " quit, removing its presence info." << endl; + + PresenceStringMap::Iterator it = d->presence_map.begin(); + const PresenceStringMap::Iterator end = d->presence_map.end(); + for ( ; it != end; ++it ) + { + ContactPresenceListCurrent list = it.data(); + ContactPresenceListCurrent::iterator cpIt = list.begin(); + while( cpIt != list.end() ) + { + ContactPresenceListCurrent::iterator gone = cpIt++; + if ( (*gone).appId == appId ) + { + list.remove( gone ); + } + } + } + m_im_client_stubs.remove( appId ); + emit sigPresenceInfoExpired(); + } +} + +void KIMProxy::contactPresenceChanged( QString uid, QCString appId, int presence ) +{ + // update the presence map + //kdDebug( 790 ) << k_funcinfo << "uid: " << uid << " appId: " << appId << " presence " << presence << endl; + ContactPresenceListCurrent current; + current = d->presence_map[ uid ]; + //kdDebug( 790 ) << "current best presence from : " << current.best().appId << " is: " << current.best().presence << endl; + AppPresenceCurrent newPresence; + newPresence.appId = appId; + newPresence.presence = presence; + + if ( current.update( newPresence ) ) + { + d->presence_map.insert( uid, current ); + emit sigContactPresenceChanged( uid ); + } +} + +int KIMProxy::presenceNumeric( const QString& uid ) +{ + AppPresenceCurrent ap; + ap.presence = 0; + if ( initialize() ) + { + ContactPresenceListCurrent presence = d->presence_map[ uid ]; + ap = presence.best(); + } + return ap.presence; +} + +QString KIMProxy::presenceString( const QString& uid ) +{ + AppPresenceCurrent ap; + ap.presence = 0; + if ( initialize() ) + { + ContactPresenceListCurrent presence = d->presence_map[ uid ]; + ap = presence.best(); + } + if ( ap.appId.isEmpty() ) + return QString::null; + else + return d->presence_strings[ ap.presence ]; +} + +QPixmap KIMProxy::presenceIcon( const QString& uid ) +{ + AppPresenceCurrent ap; + ap.presence = 0; + if ( initialize() ) + { + ContactPresenceListCurrent presence = d->presence_map[ uid ]; + ap = presence.best(); + } + if ( ap.appId.isEmpty() ) + { + //kdDebug( 790 ) << k_funcinfo << "returning a null QPixmap because we were asked for an icon for a uid we know nothing about" << endl; + return QPixmap(); + } + else + { + //kdDebug( 790 ) << k_funcinfo << "returning this: " << d->presence_icons[ ap.presence ] << endl; + return SmallIcon( d->presence_icons[ ap.presence ]); + } +} + +QStringList KIMProxy::allContacts() +{ + QStringList value = d->presence_map.keys(); + return value; +} + +QStringList KIMProxy::reachableContacts() +{ + QStringList value; + + if ( initialize() ) + { + QDictIterator<KIMIface_stub> it( m_im_client_stubs ); + for ( ; it.current(); ++it ) + { + value += it.current()->reachableContacts( ); + } + } + return value; +} + +QStringList KIMProxy::onlineContacts() +{ + QStringList value; + PresenceStringMap::iterator it = d->presence_map.begin(); + const PresenceStringMap::iterator end= d->presence_map.end(); + for ( ; it != end; ++it ) + if ( it.data().best().presence > 2 /*Better than Connecting, ie Away or Online*/ ) + value.append( it.key() ); + + return value; +} + +QStringList KIMProxy::fileTransferContacts() +{ + QStringList value; + + if ( initialize() ) + { + QDictIterator<KIMIface_stub> it( m_im_client_stubs ); + for ( ; it.current(); ++it ) + { + value += it.current()->fileTransferContacts( ); + } + } + return value; +} + +bool KIMProxy::isPresent( const QString& uid ) +{ + return ( !d->presence_map[ uid ].isEmpty() ); +} + +QString KIMProxy::displayName( const QString& uid ) +{ + QString name; + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + name = s->displayName( uid ); + } + //kdDebug( 790 ) << k_funcinfo << name << endl; + return name; +} + +bool KIMProxy::canReceiveFiles( const QString & uid ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + return s->canReceiveFiles( uid ); + } + return false; +} + +bool KIMProxy::canRespond( const QString & uid ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + return s->canRespond( uid ); + } + return false; +} + +QString KIMProxy::context( const QString & uid ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + return s->context( uid ); + } + return QString::null; +} + +void KIMProxy::chatWithContact( const QString& uid ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + { + kapp->updateRemoteUserTimestamp( s->app() ); + s->chatWithContact( uid ); + } + } + return; +} + +void KIMProxy::messageContact( const QString& uid, const QString& message ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForUid( uid ) ) + { + kapp->updateRemoteUserTimestamp( s->app() ); + s->messageContact( uid, message ); + } + } + return; +} + +void KIMProxy::sendFile(const QString &uid, const KURL &sourceURL, const QString &altFileName, uint fileSize ) +{ + if ( initialize() ) + { + QDictIterator<KIMIface_stub> it( m_im_client_stubs ); + for ( ; it.current(); ++it ) + { + if ( it.current()->canReceiveFiles( uid ) ) + { + kapp->updateRemoteUserTimestamp( it.current()->app() ); + it.current()->sendFile( uid, sourceURL, altFileName, fileSize ); + break; + } + } + } + return; +} + +bool KIMProxy::addContact( const QString &contactId, const QString &protocol ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForProtocol( protocol ) ) + return s->addContact( contactId, protocol ); + } + return false; +} + +QString KIMProxy::locate( const QString & contactId, const QString & protocol ) +{ + if ( initialize() ) + { + if ( KIMIface_stub* s = stubForProtocol( protocol ) ) + return s->locate( contactId, protocol ); + } + return QString::null; +} + +bool KIMProxy::imAppsAvailable() +{ + return ( !m_im_client_stubs.isEmpty() ); +} + +bool KIMProxy::startPreferredApp() +{ + QString preferences = QString("[X-DCOP-ServiceName] = '%1'").arg( preferredApp() ); + // start/find an instance of DCOP/InstantMessenger + QString error; + QCString dcopService; + // Get a preferred IM client. + // The app will notify itself to us using registeredToDCOP, so we don't need to record a stub for it here + // FIXME: error in preferences, see debug output + preferences = QString::null; + int result = KDCOPServiceStarter::self()->findServiceFor( IM_SERVICE_TYPE, QString::null, preferences, &error, &dcopService ); + + kdDebug( 790 ) << k_funcinfo << "error was: " << error << ", dcopService: " << dcopService << endl; + + return ( result == 0 ); +} + + +void KIMProxy::pollAll( const QString &uid ) +{ +/* // We only need to call this function if we don't have any data at all + // otherwise, the data will be kept fresh by received presence change + // DCOP signals + if ( !d->presence_map.contains( uid ) ) + { + AppPresence *presence = new AppPresence(); + // record current presence from known clients + QDictIterator<KIMIface_stub> it( m_im_client_stubs ); + for ( ; it.current(); ++it ) + { + presence->insert( it.currentKey().ascii(), it.current()->presenceStatus( uid ) ); // m_im_client_stubs has qstring keys... + } + d->presence_map.insert( uid, presence ); + }*/ +} + +void KIMProxy::pollApp( const QCString & appId ) +{ + //kdDebug( 790 ) << k_funcinfo << endl; + KIMIface_stub * appStub = m_im_client_stubs[ appId ]; + QStringList contacts = m_im_client_stubs[ appId ]->allContacts(); + QStringList::iterator it = contacts.begin(); + QStringList::iterator end = contacts.end(); + for ( ; it != end; ++it ) + { + ContactPresenceListCurrent current = d->presence_map[ *it ]; + AppPresenceCurrent ap; + ap.appId = appId; + ap.presence = appStub->presenceStatus( *it ); + current.append( ap ); + + d->presence_map.insert( *it, current ); + if ( current.update( ap ) ) + emit sigContactPresenceChanged( *it ); + //kdDebug( 790 ) << " uid: " << *it << " presence: " << ap.presence << endl; + } +} + +KIMIface_stub * KIMProxy::stubForUid( const QString &uid ) +{ + // get best appPresence + AppPresenceCurrent ap = d->presence_map[ uid ].best(); + // look up the presence string from that app + return m_im_client_stubs.find( ap.appId ); +} + +KIMIface_stub * KIMProxy::stubForProtocol( const QString &protocol) +{ + KIMIface_stub * app; + // see if the preferred client supports this protocol + QString preferred = preferredApp(); + if ( ( app = m_im_client_stubs.find( preferred ) ) ) + { + if ( app->protocols().grep( protocol ).count() > 0 ) + return app; + } + // preferred doesn't do this protocol, try the first of the others that says it does + QDictIterator<KIMIface_stub> it( m_im_client_stubs ); + for ( ; it.current(); ++it ) + { + if ( it.current()->protocols().grep( protocol ).count() > 0 ) + return it.current(); + } + return 0L; +} + +QString KIMProxy::preferredApp() +{ + KConfig *store = new KSimpleConfig( IM_CLIENT_PREFERENCES_FILE ); + store->setGroup( IM_CLIENT_PREFERENCES_SECTION ); + QString preferredApp = store->readEntry( IM_CLIENT_PREFERENCES_ENTRY ); + //kdDebug( 790 ) << k_funcinfo << "found preferred app: " << preferredApp << endl; + return preferredApp; +} + +#include "kimproxy.moc" diff --git a/interfaces/kimproxy/library/kimproxy.h b/interfaces/kimproxy/library/kimproxy.h new file mode 100644 index 000000000..6f56a0f13 --- /dev/null +++ b/interfaces/kimproxy/library/kimproxy.h @@ -0,0 +1,654 @@ +/* + kimproxy.h + + IM service library for KDE + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KIMPROXY_H +#define KIMPROXY_H + +#include <qdict.h> +#include <qmap.h> +#include <qptrdict.h> +#include <qstringlist.h> + + +#define IM_SERVICE_TYPE "DCOP/InstantMessenger" +#define IM_CLIENT_PREFERENCES_FILE "default_components" +#define IM_CLIENT_PREFERENCES_SECTION "InstantMessenger" +#define IM_CLIENT_PREFERENCES_ENTRY "imClient" + +#include "kimproxyiface.h" + +class DCOPClient; +class KIMIface_stub; +class KURL; +class ContactPresenceListCurrent; + +/** FIXME: remove for KDE4, binary compability again. */ +typedef QMap<QCString, int> AppPresence; // appId->presence; contains all applications' ideas of a user's presence +typedef QDict<AppPresence> PresenceMap; // uid->AppPresence; contains a AppPresences for all users +/** FIXME: remove presenceMap and call this presenceMap in KDE4. This hack is for binary compatibility */ +typedef QMap<QString, ContactPresenceListCurrent> PresenceStringMap; + +/** + * @brief Provides access to instant messenger programs which implement KDE's + * instant messanger interface KIMIface + * + * This class provides an easy-to-use interface to all running instant + * messengers or chat programs that implement KIMIface. + * + * It works simultaneously with any running programs that implement the + * ServiceType @c DCOP/InstantMessenger. + * + * IM-contacts are identified using unique identifier strings (UID) used by + * KDE's address book framework KABC. + * However the use of the address book API is optional, KIMProxy provides + * methods to fetch lists of available contact UIDs from the applications. + * If a UID is reachable with more than one program, KIMProxy aggregates the + * available information and presents the 'best' presence. For example, for a + * contact who can be seen to be @c Away in @c IRC on program A but @c Online + * using @c ICQ on program B, the information from program B will be used. + * + * KIMProxy is designed for simple information in a wide number of cases, not + * for detailed messaging. + * + * The class is implemented as a singleton, so whenever you need access to + * one of its methods, just retrieve the single instance using instance(). + * The following code snippet demonstrated how to send a message to all + * reachable IM-contacts: + * @code + * // get proxy instance + * KIMProxy* proxy = KIMProxy::instance(); + * + * // check if there are suitable applications reachable + * if (!proxy->initialize()) return; + * + * QString message = "Hi!\nHow are you on this wonderful day?"; + * + * // iterate over the list of reachable contacts + * QStringList reachableContacts = proxy->reachableContacts(); + * for (QStringList::const_iterator it = reachableContacts.begin(); + * it != reachableContacts.end(); ++it) + * { + proxy->messageContact(*it, message); + * } + * @endcode + * + * @note While it is possible to communicate with each of those application's + * by DCOP using KIMProxy has the advantage of communicating with all + * applications simultaneously and thus getting an augmented view of + * availability, capability and presence (online status) of IM-contacts. + * + * @see KIMIface + * @see KABC::AddressBook + * @see KABC::Addressee + * + * @since 3.3 + * @author Will Stephenson <lists@stevello.free-online.co.uk> + */ +class KIMPROXY_EXPORT KIMProxy : public QObject, virtual public KIMProxyIface +{ + Q_OBJECT + struct Private; + + template<class> friend class KStaticDeleter; + ~KIMProxy(); + + public: + /** + * @brief Obtain an instance of KIMProxy + * + * Creates a new instance if it is called for the first time. + * Call initialize() to check if there are applications available for + * communication. + * + * @note KIMProxy uses DCOPClient::setNotifications() to make sure + * it updates its information about IM applications it interacts with, + * e.g. that it gets notified about newly available applications or + * about applications exiting + * + * @param client your application's DCOP client + * @return the singleton instance of this class + */ + static KIMProxy * instance( DCOPClient * client ); + + /** + * @brief Get the proxy ready to connect + * + * Discover any running IM clients and setup communication handlers for + * them. The list of available clients is updated automatically + * through notification about added or removed DCOP applications as + * provided by DCOPClient. + * + * It is safe to call this method more than once, initialization only + * occurs at the first time. + * + * @return whether the proxy is ready to use. + * @c false if there are no suitable apps running + */ + bool initialize(); + + /** + * @brief Obtain a list of IM-contacts known to IM-applications + * + * Returns a list of KABC UIDs gathered by merging the lists of + * each application the proxy can communicate with. + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @return a list of KABC UIDs known to any IM-application + * + * @see reachableContacts() + * @see onlineContacts() + * @see fileTransferContacts() + * @see isPresent() + * @see KABC::Addressee::uid() + */ + QStringList allContacts(); + + /** + * @brief Obtain a list of IM-contacts that are currently reachable + * + * Returns a list of KABC UIDs gathered by merging the lists of + * each application the proxy can communicate with. + * + * @return a list of KABC UIDs who can receive a message, even if offline + * + * @see allContacts() + * @see onlineContacts() + * @see fileTransferContacts() + * @see messageContact() + * @see KABC::Addressee::uid() + */ + QStringList reachableContacts(); + + /** + * @brief Obtain a list of IM-contacts that are currently online + * + * Returns a list of KABC UIDs gathered by merging the lists of + * each application the proxy can communicate with. + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @return a list of KABC UIDs who are online with unspecified presence + * + * @see allContacts() + * @see reachableContacts() + * @see fileTransferContacts() + * @see messageContact() + * @see chatWithContact() + * @see KABC::Addressee::uid() + */ + QStringList onlineContacts(); + + /** + * @brief Obtain a list of IM-contacts who may receive file transfers + * + * Returned IM-contacts might not be capable of receiving file + * tranfers due to limitations of their clients or because they are + * behind a firewall. + * KIMProxy doesn't have the possibilities to discover this and will + * list them as well. + * + * Returns a list of KABC UIDs gathered by merging the lists of + * each application the proxy can communicate with. + * + * @return a list of KABC UIDs capable of file transfer + * + * @see allContacts() + * @see reachableContacts() + * @see onlineContacts() + * @see canReceiveFiles() + * @see KABC::Addressee::uid() + */ + QStringList fileTransferContacts(); + + /** + * @brief Confirm if a given contact is known to the proxy + * + * A contact is known to the proxy if it is know to at least one + * IM-application the proxy is communicating with. + * + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @param uid the KABC UID you are interested in + * @return whether any IM-program knows of this KABC UID + * + * @see allContacts() + * @see presenceString() + * @see presenceNumeric() + * @see KABC::Addressee::uid() + */ + bool isPresent( const QString& uid ); + + /** + * @brief Obtain the proxy's idea of the contact's display name + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and @c Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * Useful if KABC lookups may be too slow. + * + * @param uid the KABC UID you are interested in + * @return the corresponding display name or QString:null if the + * UID is unknown + * + * @see isPresent() + * @see presenceString() + * @see presenceNumeric() + * @see KABC::Addressee::uid() + */ + QString displayName( const QString& uid ); + + /** + * @brief Obtain the IM presence as a number for the specified contact + * + * Returns one of the following values depending on the given contact's + * presence: + * - 0 - @c Unknown: for contacts where you can not use any of the + * other values + * + * - 1 - @c Offline: for contacts that are offline, i.e. not connected + * to their IM-service. + * + * - 2 - @c Connecting + * + * - 3 - @c Away: for contacts that are connected to their IM-service + * but not @c Online + * + * - 4 - @c Online + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @param uid the KABC UID you want the presence for + * @return a numeric representation of presence - currently one of + * 0 (Unknown), 1 (Offline), 2 (Connecting), 3 (Away), + * 4 (Online). Returns 0 if the given UID is unknown + * + * @see isPresent() + * @see presenceString() + * @see presenceIcon() + * @see KIMIface::presenceStatus() + * @see KABC::Addressee::uid() + */ + int presenceNumeric( const QString& uid ); + + /** + * @brief Obtain the IM presence as a i18ned string for the specified + * contact + * + * The presence string is one of the following: + * - i18n("Unknown") + * - i18n("Offline") + * - i18n("Connecting") + * - i18n("Away") + * - i18n("Online") + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * @note The presence string is created based on the numerical + * presence value returned by the applications. It currently + * does not return the presence strings used by the applications. + * + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @param uid the KABC UID you want the presence for + * @return the i18ned string describing the contact's presence or + * QString::null if the UID is unknown + * + * @see isPresent() + * @see presenceNumeric() + * @see presenceIcon() + * @see KABC::Addressee::uid() + */ + QString presenceString( const QString& uid ); + + /** + * @brief Obtain the icon representing the IM presence for the + * specified contact + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * @note The presence icon is chosen based on the numerical + * presence value returned by the applications. It currently + * does not return the presence icon used by the applications. + * + * The method uses cached information to make it fast and not + * require actually communicating with the applications every time + * it is called. + * + * @param uid the KABC UID you want the presence icon for + * @return a pixmap representing the contact's presence or a null + * pixmap if the contact is unknown. See QPixmap::isNull() + * + * @see isPresent() + * @see presenceString() + * @see presenceNumeric() + * @see KABC::Addressee::uid() + */ + QPixmap presenceIcon( const QString& uid ); + + /** + * @brief Indicate if a given contact can receive files + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * @param uid the KABC UID you want to the file transfer capability for + * @return whether the specified contact can receive files + * + * @see fileTransferContacts() + * @see KABC::Addressee::uid() + */ + bool canReceiveFiles( const QString & uid ); + + /** + * @brief Indicate if a given contact will be able to respond + * + * Some media are unidirectional (e.g., sending SMS via a web + * interface). + * This refers to the contact's ability to respond as defined by the + * medium, not by their presence. + * + * Someone may appear offline (SMS has no presence) to you but in fact + * be able to respond. + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * @param uid the KABC UID you are interested in + * @return whether the specified contact can respond + * + * @see isPresent() + * @see KABC::Addressee::uid() + */ + bool canRespond( const QString & uid ); + + /** + * @brief Obtain the KABC UID corresponding to the given IM address + * + * @param contactId the protocol specific identifier for the contact, + * e.g. UIN for ICQ, screenname for AIM, nick for IRC + * @param protocol the IM protocol/service to check. + * See KIMIface::protocols() + * @return the KABC UID for the given contact or @c QString::null if + * not found or either input stream was empty or the protocol + * is not supported + * + * @see KIMIface::protocols() + * @see addContact() + * @see isPresent() + * @see KABC::Addressee::uid() + */ + QString locate( const QString & contactId, const QString & protocol ); + + /** + * @brief Obtain the given contact's current context (home, work, or + * any) + * + * Not all IM services/protocols support the concept of contexts. If the + * given UID maps to such a service, @c QString::null will be returned + * + * If the given KABC UID is known to more than one IM-application + * the result of the application which has the best presence for the + * contact is taken. + * For example if a contact is @c Online on ICQ and Away on AIM, the + * value returned by the application providing ICQ is taken. + * + * @param uid the KABC UID you want the context for + * @return a string describing the context, or @c QString::null if not + * supported or if the contact is unknown + * + * @see isPresent() + * @see KABC::Addressee::uid() + */ + QString context( const QString & uid ); + + /** + * @brief Start a chat session with the specified contact + * + * @param uid the KABC UID you want to chat with + * + * @see messageContact() + * @see sendFile() + * @see isPresent() + * @see reachableContacts() + * @see KABC::Addressee::uid() + */ + void chatWithContact( const QString& uid ); + + /** + * @brief Send a single message to the specified contact + * + * Any response will be handled by the IM client as a normal + * conversation. + * + * @param uid the KABC UID you want to send the message to + * @param message the message text to send to the contact + * + * @see chatWithContact() + * @see sendFile() + * @see isPresent() + * @see reachableContacts() + * @see KABC::Addressee::uid() + */ + void messageContact( const QString& uid, const QString& message ); + + /** + * @brief Send a file to the contact + * + * Initiates a file transfer with the given contact if possible. + * + * @param uid the KABC UID you want to send to + * @param sourceURL a KURL pointing to the file to send + * @param altFileName an alternate filename describing the file or a + * description or title + * @param fileSize file size in bytes + * + * @see messageContact() + * @see chatWithContact() + * @see isPresent() + * @see fileTransferContacts() + * @see KABC::Addressee::uid() + */ + void sendFile(const QString &uid, const KURL &sourceURL, + const QString &altFileName = QString::null, uint fileSize = 0); + + /** + * @brief Add a new contact given its protocol specific identifier + * + * @param contactId the protocol specific identifier for the contact + * e.g. UIN for ICQ, screenname for AIM, nick for IRC + * @param protocol the IM protocol/service to use. + * See KIMIface:::protocols() + * @return whether the add succeeded. @c false may signal already present, + * protocol not supported, or add operation not supported. + * + * @see locate() + * @see KIMIface::protocols() + */ + bool addContact( const QString &contactId, const QString &protocol ); + + /** + * @brief Checks if there are any compatible instant messaging + * applications available + * + * Available means that they are started and registered with DCOP + * and implementing the correct DCOP service. + * This information will be updated on the first call to initialize() + * and whenever an application registers or unregisters with DCOP, + * i.e. the information will be kept up to date. + * + * @return @c true if there are any apps available + */ + bool imAppsAvailable(); + + /** + * @brief Start the user's preferred IM application + * @return whether a preferred app was found. No guarantee that it + * started correctly + */ + bool startPreferredApp(); + + /** + * Just exists to let the IDL compiler make the DCOP signal for this + */ + void contactPresenceChanged( QString uid, QCString appId, int presence ); + + public slots: + /** + * @brief Updates the proxy's data after a new application registered + * with DCOP + * + * Checks if the application specified by the given DCOP application + * identifier implements the instant messenger service. + * + * @param appId the DCOP application ID of the newly registered + * application + * + * @see DCOPClient::applicationRegistered() + */ + void registeredToDCOP( const QCString& appId ); + + /** + * @brief Updates the proxy's data after an application unregistered + * with DCOP + * + * If the application specified by the given DCOP application + * identifier is one of the instant messenger applications of the + * proxy, it will remove the presence information it gathered from it + * earlier on. + * + * Emits sigPresenceInfoExpired() to let the using applcation know + * its presence related information might need updating. + * + * @param appId the DCOP application ID of the now unregistered + * application + * + * @see DCOPClient::applicationRemoved() + */ + void unregisteredFromDCOP( const QCString& appId ); + signals: + /** + * @brief Indicates that the specified IM-contact's presence changed + * + * @param uid the KABC UID whose presence changed + * + * @see isPresent() + * @see presenceNumeric() + * @see presenceIcon() + * @see KABC::Addressee::uid() + */ + void sigContactPresenceChanged( const QString &uid ); + + /** + * @brief Indicates that presence information obtained earlier on might + * not be valid any longer + * + * After the sources of presence information have changed so any + * previously supplied presence info is invalid. + */ + void sigPresenceInfoExpired(); + protected: + /** + * Bootstrap our presence data for a newly registered app + */ + void pollApp( const QCString & appId ); + /** + * Bootstrap our presence data by polling all known apps + */ + void pollAll( const QString &uid ); + + /** + * Update our records with the given data + */ + bool updatePresence( const QString &uid, const QCString &appId, int presence ); + + /** + * Get the name of the user's IM application of choice + */ + QString preferredApp(); + + /** + * Get the app stub best able to reach this uid + */ + KIMIface_stub * stubForUid( const QString &uid ); + + /** + * Get the app stub for this protocol. + * Take the preferred app first, then any other. + */ + KIMIface_stub * stubForProtocol( const QString &protocol ); + + private: + // client stubs used to get presence + // appId (from DCOP) -> KIMIface_stub + QDict<KIMIface_stub> m_im_client_stubs; + // map containing numeric presence and the originating application ID for each KABC uid we know of + // KABC Uid -> (appId, numeric presence )(AppPresence) + PresenceMap m_presence_map; + // cache of the client strings in use by each application + // dictionary of KIMIface_stub -> map of numeric presence -> string presence + // FIXME: remove for KDE4 - UNUSED but maintained for binary compatibility in KDE 3.4 + QPtrDict<int> m_client_presence_strings; + Private * d; + bool m_apps_available; + bool m_initialized; + /** + * Construct an instance of the proxy library. + */ + KIMProxy( DCOPClient * client); + static KIMProxy * s_instance; +}; + +#endif + diff --git a/interfaces/kimproxy/library/kimproxyiface.h b/interfaces/kimproxy/library/kimproxyiface.h new file mode 100644 index 000000000..7c99bce4e --- /dev/null +++ b/interfaces/kimproxy/library/kimproxyiface.h @@ -0,0 +1,38 @@ +/* + kimproxyiface.cpp + + IM service library for KDE + + DCOP interface to allow us to receive DCOP signals + + Copyright (c) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KIMPROXYIFACE_H +#define KIMPROXYIFACE_H + +#include <dcopobject.h> + +class KIMProxyIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + virtual void contactPresenceChanged( QString uid, QCString appId, int presence ) = 0; +}; + +#endif |