[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kopete-devel
Subject:    [kopete-devel] [Patch] Extended D-Bus Interface
From:       Dennis_Nienhüser <earthwings () gentoo ! org>
Date:       2008-08-16 18:46:47
Message-ID: 48A72097.7040809 () gentoo ! org
[Download RAW message or body]

Hi,

currently our D-Bus interface is a bit (too) limited. As it's not clear
when telepathy and co. will make the current approach obsolete, here's a
patch to make more interesting things available via D-Bus. I'll add some
disclaimers that it is subject to change and might be removed before 4.2
(as discussed on IRC).

Changes include:
- Methods previously using the displayName to locate contacts
(unreliable) additionally understand protocol:account:contact triplets
(as returned by contacts()), contact ids and for backward compatibility
(and lazy people) still display names.
- contactsByFilter() also supports "away" as filter (previously
"online", "reachable", filecapable").
- new method openChat, similar to sendMessage except that no message is
sent.
- new method contactProperties reporting a QVariantMap with the
following contact properties: id, displayName, online status, status
message, reachability, path to avatar, pending messages (stringlist)
- new signal contactChanged announcing that one of the properties has
changed (so applications don't have to poll for it)

I tested this interface with the contacts plasmoid in playground and it
seems to work nice.

Comments appreciated.

Regards,
Dennis


["kopete-dbus.diff" (text/x-diff)]

Index: kopete/kopete/kopetedbusinterface_p.cpp
===================================================================
--- kopete/kopete/kopetedbusinterface_p.cpp	(revision 0)
+++ kopete/kopete/kopetedbusinterface_p.cpp	(revision 0)
@@ -0,0 +1,187 @@
+/*
+ kopetedbusinterfaceprivate.h - Kopete D-Bus interface private class
+
+ Copyright (c) 2008      by Dennis Nienhüser <earthwings@gentoo.org>
+ 
+ Kopete    (c) 2002-2008 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of the GNU Lesser General Public            *
+ * License as published by the Free Software Foundation; either          *
+ * version 2 of the License, or (at your option) any later version.      *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#include "kopetedbusinterface_p.h"
+
+#include <QtCore/QTimer>
+
+#include <kopetecontactlist.h>
+#include <kopetemetacontact.h>
+#include <kopetecontact.h>
+#include <kopetechatsessionmanager.h>
+#include <kopeteviewmanager.h>
+#include <kopetemessageevent.h>
+
+ContactStalker::ContactStalker(Kopete::MetaContact *contact)
+{
+    m_contact = contact;
+    QObject::connect( Kopete::ContactList::self(), 
+    		SIGNAL(metaContactRemoved( Kopete::MetaContact *)),
+    		this, SLOT(slotMetaContactRemoved(Kopete::MetaContact *)) );
+    QObject::connect( contact, \
SIGNAL(onlineStatusChanged(Kopete::MetaContact*,Kopete::OnlineStatus::StatusType)), + \
this, SLOT(slotEmitSignalDelayed())); +    QObject::connect( contact, \
SIGNAL(displayNameChanged(const QString &, const QString &)), +            this, \
SLOT(slotEmitSignalDelayed())); +    QObject::connect( contact, \
SIGNAL(photoChanged()), +            this, SLOT(slotEmitSignalDelayed()));
+    QObject::connect( contact, SIGNAL(contactAdded(Kopete::Contact*)),
+            this, SLOT(slotEmitSignalDelayed()));
+    QObject::connect( contact, SIGNAL(contactRemoved(Kopete::Contact*)),
+            this, SLOT(slotEmitSignalDelayed()));    
+    
+    QObject::connect(Kopete::ChatSessionManager::self(), 
+    		SIGNAL( display( Kopete::Message &, Kopete::ChatSession *) ), 
+    		this, SLOT ( messageAppended( Kopete::Message &, Kopete::ChatSession *) ) );
+    
+    m_lastChange = QTime::currentTime();
+    slotEmitSignal();
+}
+
+void ContactStalker::slotEmitSignalDelayed()
+{
+    const int timeout(1500);
+    
+    if (m_lastChange.elapsed() >= timeout)
+    {
+        m_lastChange = QTime::currentTime();   
+        QTimer::singleShot(timeout, this, SLOT(slotEmitSignal()));
+    }
+}
+
+void ContactStalker::slotEmitSignal()
+{
+	if (m_contact)
+	{
+		emit contactChanged(m_contact->metaContactId());
+	}
+}
+
+void ContactStalker::messageAppended(Kopete::Message &message,
+        Kopete::ChatSession *session)
+{
+    Q_UNUSED(session);
+    if(!m_contact)
+    {
+    	return;
+    }
+
+    if ( message.direction() == Kopete::Message::Inbound ) {
+    	QString contactId = message.from()->metaContact()->metaContactId();
+    	if (contactId == m_contact->metaContactId())
+    	{
+    		foreach(Kopete::Contact *subContact, m_contact->contacts())
+    		{
+    	        QList<Kopete::MessageEvent*> pendingMessages = \
KopeteViewManager::viewManager()->pendingMessages(subContact); +    	        \
foreach(Kopete::MessageEvent *event, pendingMessages) +    	        {
+    	        	connect(event, SIGNAL(done(Kopete::MessageEvent*)), this, \
SLOT(slotEmitSignalDelayed())); +    	        }
+    		}
+    		
+    		emit contactChanged(contactId);
+    	}
+    }
+}
+
+void ContactStalker::slotMetaContactRemoved(Kopete::MetaContact *contact)
+{
+	if (contact == m_contact)
+	{
+		m_contact = 0L;
+		emit contactChanged(contact->metaContactId());
+	}
+}
+
+KopeteDBusInterfacePrivate::KopeteDBusInterfacePrivate()
+{
+    QObject::connect(Kopete::ContactList::self(), 
+    		SIGNAL(metaContactAdded(Kopete::MetaContact*)),
+    		this, SLOT(slotMetaContactAdded(Kopete::MetaContact*)));	
+
+    foreach( Kopete::MetaContact *contact, \
Kopete::ContactList::self()->metaContacts() ) +    { 
+        this->slotMetaContactAdded(contact);
+    }
+}
+
+void KopeteDBusInterfacePrivate::slotMetaContactAdded(
+        Kopete::MetaContact* contact)
+{
+    if ( contact ) {
+        ContactStalker * stalker = new ContactStalker(contact);
+        connect( stalker, SIGNAL(contactChanged(QString)), 
+                this, SIGNAL(contactChanged(QString)));
+    }
+}
+
+QStringList KopeteDBusInterfacePrivate::listContact(const QList<
+        Kopete::MetaContact*> &contactList)
+{
+    QStringList result;
+
+    foreach(Kopete::MetaContact *contact, contactList){ 
+    result << contact->metaContactId();
+}
+
+return result;
+}
+
+Kopete::OnlineStatusManager::Categories KopeteDBusInterfacePrivate::status2Value(
+        const QString &status)
+{
+    Kopete::OnlineStatusManager::Categories statusValue;
+    if ( status.toLower() == QLatin1String("online") || status.toLower()
+            == QLatin1String("available") ) {
+        statusValue = Kopete::OnlineStatusManager::Online;
+    } else if ( status.toLower() == QLatin1String("busy") ) {
+        statusValue = Kopete::OnlineStatusManager::Busy;
+    } else if ( status.toLower() == QLatin1String("away") ) {
+        statusValue = Kopete::OnlineStatusManager::Away;
+    }
+
+    return statusValue;
+}
+
+Kopete::MetaContact *KopeteDBusInterfacePrivate::findContact(
+        const QString &nameOrId)
+{
+    Kopete::MetaContact *contact = 0L;
+
+    if ( nameOrId.count(":") == 2 ) {
+        QStringList tokens = nameOrId.split(":");
+        Q_ASSERT(tokens.size() == 3);
+        Kopete::Contact *candidate = Kopete::ContactList::self()->findContact(
+                tokens.at(0), tokens.at(1), tokens.at(2));
+        if ( candidate ) {
+            contact = candidate->metaContact();
+        }
+    }
+
+    if ( !contact ) {
+        contact = Kopete::ContactList::self()->findMetaContactByContactId(
+                nameOrId);
+    }
+
+    if ( !contact ) {
+        contact = Kopete::ContactList::self()->findMetaContactByDisplayName(
+                nameOrId);
+    }
+
+    return contact;
+}
+
+#include "kopetedbusinterface_p.moc"
Index: kopete/kopete/kopetedbusinterface.cpp
===================================================================
--- kopete/kopete/kopetedbusinterface.cpp	(revision 847746)
+++ kopete/kopete/kopetedbusinterface.cpp	(working copy)
@@ -40,47 +40,22 @@
 #include <kopetechatsession.h>
 #include <kopetegroup.h>
 #include <kopetepluginmanager.h>
+#include <kopetepicture.h>
+#include <kopeteviewmanager.h>
+#include <kopetemessageevent.h>
 
 // Local includes
 #include "kopeteadaptor.h"
+#include "kopetedbusinterface_p.h"
 
-QStringList listContact(const QList<Kopete::MetaContact*> &contactList)
-{
-	QStringList result;
-
-	foreach(Kopete::MetaContact *contact, contactList)
-	{
-		result << contact->metaContactId();
-	}
-
-	return result;
-}
-
-Kopete::OnlineStatusManager::Categories status2Value(const QString &status)
-{
-	Kopete::OnlineStatusManager::Categories statusValue;
-	if( status.toLower() == QLatin1String("online") || status.toLower() == \
                QLatin1String("available") )
-	{
-		statusValue = Kopete::OnlineStatusManager::Online;
-	}
-	else if( status.toLower() == QLatin1String("busy") )
-	{
-		statusValue = Kopete::OnlineStatusManager::Busy;
-	}
-	else if( status.toLower() == QLatin1String("away") )
-	{
-		statusValue = Kopete::OnlineStatusManager::Away;
-	}
-
-	return statusValue;
-}
-
-KopeteDBusInterface::KopeteDBusInterface(QObject *parent)
- : QObject(parent)
+KopeteDBusInterface::KopeteDBusInterface(QObject *parent) :
+	QObject(parent), d(new KopeteDBusInterfacePrivate())
 {
 	setObjectName("KopeteDBusInterface");
 	new KopeteAdaptor(this);
 	QDBusConnection::sessionBus().registerObject("/Kopete", this);
+
+	QObject::connect(d, SIGNAL(contactChanged(QString)), this, \
SIGNAL(contactChanged(QString)));  }
 
 KopeteDBusInterface::~KopeteDBusInterface()
@@ -91,24 +66,29 @@
 {
     QStringList list;
     foreach(KPluginInfo p, \
Kopete::PluginManager::self()->availablePlugins("Protocols")) +	{ 
         list << p.name();
+	}
     return list;
 }
 
 QStringList KopeteDBusInterface::contacts() const
 {
-	return listContact(Kopete::ContactList::self()->metaContacts());
+	return d->listContact(Kopete::ContactList::self()->metaContacts());
 }
 
 QStringList KopeteDBusInterface::contactsByFilter(const QString &filter) const
 {
-	QList<Kopete::MetaContact*> completeList = \
Kopete::ContactList::self()->metaContacts(); +	QList<Kopete::MetaContact*> \
completeList = +			Kopete::ContactList::self()->metaContacts();
 	QList<Kopete::MetaContact*> filteredList;
 
 	Kopete::MetaContact *contact;
 	
 	if( filter.toLower() == QLatin1String("online") )
 	{
+		// "online" returns contacts that are not offline, which means that
+		// those being away, busy etc. are included as well. 
 		foreach(contact, completeList)
 		{
 			if( contact->isOnline() )
@@ -131,11 +111,22 @@
 				filteredList << contact;
 		}
 	}
+	else if ( filter.toLower() == QLatin1String("away") )
+	{
+		foreach(contact, completeList)
+		{
+			if( contact->status() == Kopete::OnlineStatus::Away )
+			{
+				filteredList << contact;
+			}
+		}
+	}
 
-	return listContact(filteredList);
+	return d->listContact(filteredList);
 }
 
-void KopeteDBusInterface::setIdentityNickName(const QString &nickName, const QString \
&identityId) +void KopeteDBusInterface::setIdentityNickName(const QString &nickName,
+		const QString &identityId)
 {
 	Kopete::Identity *identity = 0;
 
@@ -150,11 +141,13 @@
 
 	if( identity )
 	{
-		identity->setProperty( Kopete::Global::Properties::self()->nickName(), nickName );
+		identity->setProperty(Kopete::Global::Properties::self()->nickName(),
+				nickName);
 	}
 }
 
-void KopeteDBusInterface::setIdentityAvatar(const QString &avatarUrl, const QString \
&identityId) +void KopeteDBusInterface::setIdentityAvatar(const QString &avatarUrl,
+		const QString &identityId)
 {
 	Kopete::Identity *identity = 0;
 
@@ -177,11 +170,13 @@
 		
 		avatarEntry = Kopete::AvatarManager::self()->add(avatarEntry);
 
-		identity->setProperty( Kopete::Global::Properties::self()->photo(), \
avatarEntry.path ); +		identity->setProperty(Kopete::Global::Properties::self()->photo(),
 +				avatarEntry.path);
 	}
 }
 
-void KopeteDBusInterface::setIdentityOnlineStatus(const QString &status, const \
QString &message, const QString &identityId) +void \
KopeteDBusInterface::setIdentityOnlineStatus(const QString &status, +		const QString \
&message, const QString &identityId)  {
 	Kopete::Identity *identity = 0;
 	
@@ -196,7 +191,7 @@
 
 	if( identity )
 	{
-		identity->setOnlineStatus( status2Value(status), message );
+		identity->setOnlineStatus(d->status2Value(status), message);
 	}
 }
 
@@ -214,11 +209,14 @@
 
 QString KopeteDBusInterface::labelForIdentity(const QString & id) const
 {
-    Kopete::Identity * identity = Kopete::IdentityManager::self()->findIdentity(id);
-    if ( identity ) {
+	Kopete::Identity * identity =
+			Kopete::IdentityManager::self()->findIdentity(id);
+	if (identity)
+	{
         return identity->label();
     }
-	else {
+	else
+	{
 		return QString();
 	}
 }
@@ -237,17 +235,22 @@
 
 void KopeteDBusInterface::connectAll()
 {
-	Kopete::AccountManager::self()->setOnlineStatus( \
Kopete::OnlineStatusManager::Online, QString(), \
Kopete::AccountManager::ConnectIfOffline ); \
+	Kopete::AccountManager::self()->setOnlineStatus( \
+			Kopete::OnlineStatusManager::Online, QString(), \
+			Kopete::AccountManager::ConnectIfOffline);  }
 
 void KopeteDBusInterface::disconnectAll()
 {
-	Kopete::AccountManager::self()->setOnlineStatus( \
Kopete::OnlineStatusManager::Offline ); \
+	Kopete::AccountManager::self()->setOnlineStatus( \
+			Kopete::OnlineStatusManager::Offline);  }
 
-void KopeteDBusInterface::setOnlineStatus(const QString &status, const QString \
&message) +void KopeteDBusInterface::setOnlineStatus(const QString &status,
+		const QString &message)
 {
-	Kopete::AccountManager::self()->setOnlineStatus( status2Value(status), message );
+	Kopete::AccountManager::self()->setOnlineStatus(d->status2Value(status),
+			message);
 }
 
 void KopeteDBusInterface::setStatusMessage(const QString &message)
@@ -255,42 +258,61 @@
 	Kopete::AccountManager::self()->setStatusMessage(message);
 }
 
-void KopeteDBusInterface::sendMessage(const QString &displayName, const QString \
&message) +void KopeteDBusInterface::sendMessage(const QString &contactId,
+		const QString &message)
 {
-	Kopete::MetaContact *destMetaContact = \
Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); \
+	Kopete::MetaContact *destMetaContact = d->findContact(contactId);  if( \
destMetaContact && destMetaContact->isReachable() )  {
 		Kopete::Contact *destContact = destMetaContact->execute();
 		if( destContact )
 		{
-			Kopete::Message newMessage( destContact->account()->myself(), destContact );
+			Kopete::Message newMessage(destContact->account()->myself(),
+					destContact);
 			newMessage.setPlainBody( message );
 			newMessage.setDirection( Kopete::Message::Outbound );
 
-			destContact->manager(Kopete::Contact::CanCreate)->sendMessage( newMessage );
+			destContact->manager(Kopete::Contact::CanCreate)->sendMessage(
+					newMessage);
+		}
+	}
+}
+
+void KopeteDBusInterface::openChat(const QString &contactId)
+{
+	Kopete::MetaContact *contact = d->findContact(contactId);
+	if (contact && contact->isReachable())
+	{
+		Kopete::Contact *preferredContact = contact->preferredContact();
+		if (preferredContact && preferredContact->account()
+				&& preferredContact != preferredContact->account()->myself())
+		{
+			contact->execute();
 		}
 	}
 }
 
 QString KopeteDBusInterface::getDisplayName(const QString &contactId)
 {
-	Kopete::MetaContact *contact = \
Kopete::ContactList::self()->findMetaContactByContactId(contactId); \
+	Kopete::MetaContact *contact = d->findContact(contactId);  if ( contact )
 		return contact->displayName();
 	else
 		return "";
 }
 
-bool KopeteDBusInterface::isContactOnline(const QString &displayName)
+bool KopeteDBusInterface::isContactOnline(const QString &contactId)
 {
-	Kopete::MetaContact *contact = \
Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); \
+	Kopete::MetaContact *contact = d->findContact(contactId);  if ( contact )
 		return contact->isOnline();
 	else
 		return false;
 }
 
-bool KopeteDBusInterface::addContact(const QString &protocolName, const QString \
&accountId, const QString &contactId, const QString &displayName, const QString \
&groupName) +bool KopeteDBusInterface::addContact(const QString &protocolName,
+		const QString &accountId, const QString &contactId,
+		const QString &displayName, const QString &groupName)
 {
 	QString protocolId = protocolName;
 	if( !protocolName.contains("Protocol") )
@@ -299,7 +321,8 @@
 	}
 
 	// Find the account using the given parameters on D-Bus
-	Kopete::Account *account = Kopete::AccountManager::self()->findAccount( protocolId, \
accountId ); +	Kopete::Account *account = \
Kopete::AccountManager::self()->findAccount( +			protocolId, accountId);
 
 	if( account )
 	{
@@ -318,7 +341,8 @@
 		if ( !groupName.isEmpty() )
 			realGroup = Kopete::ContactList::self()->findGroup( groupName );
 
-		account->addContact( contactId, contactName, realGroup, \
Kopete::Account::DontChangeKABC); +		account->addContact(contactId, contactName, \
realGroup, +				Kopete::Account::DontChangeKABC);
 
 		return true;
 	}
@@ -326,9 +350,10 @@
 	return false;
 }
 
-void KopeteDBusInterface::sendFile(const QString &displayName, const QString \
&fileUrl) +void KopeteDBusInterface::sendFile(const QString &contactId,
+		const QString &fileUrl)
 {
-	Kopete::MetaContact *destMetaContact = \
Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); \
+	Kopete::MetaContact *destMetaContact = d->findContact(contactId);  if( \
destMetaContact && destMetaContact->isReachable() )  {
 		Kopete::Contact *destContact = destMetaContact->execute();
@@ -339,7 +364,8 @@
 	}
 }
 
-bool KopeteDBusInterface::isConnected(const QString &protocolName, const QString \
&accountId) +bool KopeteDBusInterface::isConnected(const QString &protocolName,
+		const QString &accountId)
 {
 	QString protocolId = protocolName;
 	if( !protocolName.contains("Protocol") )
@@ -347,11 +373,13 @@
 		protocolId += QLatin1String("Protocol");
 	}
 
-	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, \
accountId); +	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
+			protocolId, accountId);
 	return account ? account->isConnected() : false;
 }
 
-void KopeteDBusInterface::connect(const QString &protocolName, const QString \
&accountId) +void KopeteDBusInterface::connect(const QString &protocolName,
+		const QString &accountId)
 {
 	QString protocolId = protocolName;
 	if( !protocolName.contains("Protocol") )
@@ -359,14 +387,16 @@
 		protocolId += QLatin1String("Protocol");
 	}
 
-	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, \
accountId); +	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
+			protocolId, accountId);
 	if( account )
 	{
 		account->connect();
 	}
 }
 
-void KopeteDBusInterface::disconnect(const QString &protocolName, const QString \
&accountId) +void KopeteDBusInterface::disconnect(const QString &protocolName,
+		const QString &accountId)
 {
 	QString protocolId = protocolName;
 	if( !protocolName.contains("Protocol") )
@@ -374,11 +404,56 @@
 		protocolId += QLatin1String("Protocol");
 	}
 
-	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, \
accountId); +	Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
+			protocolId, accountId);
 	if( account )
 	{
 		account->disconnect();
 	}
 }
 
+QVariantMap KopeteDBusInterface::contactProperties(const QString &contactId)
+{
+	QVariantMap properties;
+	Kopete::MetaContact *contact = d->findContact(contactId);
+
+	if (contact)
+	{
+		properties["status"] = Kopete::OnlineStatus::statusTypeToString(
+				contact->status());
+		properties["message_reachable"] = contact->isReachable();
+		properties["file_reachable"] = contact->canAcceptFiles();
+		properties["display_name"] = contact->displayName();
+		properties["id"] = contact->metaContactId();
+		if (contact->photoSource() == Kopete::MetaContact::SourceCustom)
+		{
+			properties["picture"] = contact->customPhoto().prettyUrl();
+		}
+		else
+		{
+			properties["picture"] = contact->picture().path();
+		}
+		properties["idle_time"] = qulonglong(contact->idleTime());
+		if (contact->preferredContact())
+		{
+			/** @todo: export status message title as well or merge both? */
+			properties["status_message"]
+					= contact->preferredContact()->statusMessage().message();
+		}
+		
+		QStringList messages;
+		foreach(Kopete::Contact *subContact, contact->contacts())
+		{
+	        QList<Kopete::MessageEvent*> pendingMessages = \
KopeteViewManager::viewManager()->pendingMessages(subContact); +	        \
foreach(Kopete::MessageEvent *event, pendingMessages) +	        {
+	        	messages << event->message().parsedBody();
+	        }
+		}
+		properties["pending_messages"] = messages;
+	}
+
+	return properties;
+}
+
 #include "kopetedbusinterface.moc"
Index: kopete/kopete/CMakeLists.txt
===================================================================
--- kopete/kopete/CMakeLists.txt	(revision 847746)
+++ kopete/kopete/CMakeLists.txt	(working copy)
@@ -59,6 +59,7 @@
    kopeteidentitystatusbaricon.cpp
    kopeteaccountstatusbaricon.cpp
    kopetedbusinterface.cpp
+   kopetedbusinterface_p.cpp
    infoeventwidget.cpp
    )
 
Index: kopete/kopete/kopetedbusinterface_p.h
===================================================================
--- kopete/kopete/kopetedbusinterface_p.h	(revision 0)
+++ kopete/kopete/kopetedbusinterface_p.h	(revision 0)
@@ -0,0 +1,93 @@
+/*
+ kopetedbusinterfaceprivate.h - Kopete D-Bus interface private class
+
+ Copyright (c) 2008      by Dennis Nienhüser <earthwings@gentoo.org>
+ 
+ Kopete    (c) 2002-2008 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of the GNU Lesser General Public            *
+ * License as published by the Free Software Foundation; either          *
+ * version 2 of the License, or (at your option) any later version.      *
+ *                                                                       *
+ *************************************************************************
+ */
+
+#ifndef KOPETE_DBUS_INTERFACE_P_H
+#define KOPETE_DBUS_INTERFACE_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QVariantMap>
+#include <QtCore/QTime>
+
+#include "kopetemessage.h"
+#include "kopetechatsession.h"
+#include "kopetemetacontact.h"
+
+/**
+ * Tracks changes of a metacontact and reports them via signals
+ */
+class ContactStalker: public QObject
+{
+    Q_OBJECT
+    
+public:
+    ContactStalker(Kopete::MetaContact *contact);
+
+Q_SIGNALS:
+	/** Emitted whenever a property of the tracked contact changed */
+    void contactChanged(QString contactId);
+
+private Q_SLOTS:
+	void messageAppended( Kopete::Message &message, Kopete::ChatSession *session);
+
+	void slotEmitSignal();
+
+    void slotEmitSignalDelayed();
+    
+    void slotMetaContactRemoved(Kopete::MetaContact *contact);
+    
+private:
+    Kopete::MetaContact *m_contact;
+    
+    QTime m_lastChange;
+};
+
+/**
+ * Tracks changes of all metacontacts and reports them via signals.
+ * Contains helper functions for KopeteDBusInterface
+ */
+class KopeteDBusInterfacePrivate: public QObject
+{
+Q_OBJECT
+
+public:
+    KopeteDBusInterfacePrivate();
+    
+    QStringList listContact(const QList<Kopete::MetaContact*> &contactList);
+    
+    Kopete::OnlineStatusManager::Categories status2Value(const QString &status);
+    
+    /**
+     * Tries to locate a meta contact using first the protocol:account:contact
+     * triplet, if that fails the meta contact id, lastly the displayName.
+     * Returns 0 if nothing is found.
+     */
+    Kopete::MetaContact *findContact(const QString &nameOrId);
+    
+Q_SIGNALS:
+	/** 
+	 * Emmited whenever a contact's property changed 
+	 * @param contactId protocol:account:contact triplet of the 
+	 *        contact with a property change
+	 * */ 
+    void contactChanged(QString contactId);
+
+private Q_SLOTS:
+    void slotMetaContactAdded(Kopete::MetaContact* contact);
+
+};
+
+#endif // KOPETE_DBUS_INTERFACE_P_H
Index: kopete/kopete/kopetedbusinterface.h
===================================================================
--- kopete/kopete/kopetedbusinterface.h	(revision 847746)
+++ kopete/kopete/kopetedbusinterface.h	(working copy)
@@ -19,8 +19,9 @@
 #define KOPETE_DBUSINTERFACE_H
 
 #include <QtCore/QObject>
+#include <QtCore/QVariantMap>
 
-class QStringList;
+class KopeteDBusInterfacePrivate;
 
 /**
  * @brief Public D-Bus interface for Kopete
@@ -167,10 +168,16 @@
 
 	/**
 	 * @brief Send a message to the given contact
-	 * @param displayName Metacontact display name to send a messasge
+     * @param contactId Metacontact ID or displayName to send a message to
 	 * @param message The message to send
 	 */
-	void sendMessage(const QString &displayName, const QString &message);
+	void sendMessage(const QString &contactId, const QString &message);
+	
+    /**
+     * Open a chat window for the given contact
+     * @param contactId Metacontact ID or displayName
+     */
+    void openChat(const QString &contactId);
 	
 	/**
 	 * @brief Adds a contact with the specified params.
@@ -186,26 +193,39 @@
 
 	/**
 	 * @brief Send a file to the given contact
-	 * @param displayName Metacontact display name to send a file
+     * @param contactId Metacontact ID or displayName to send a file to
 	 * @param fileUrl Url of the file to send
 	 */
-	void sendFile( const QString &displayName, const QString &fileUrl );
+	void sendFile( const QString &contactId, const QString &fileUrl );
 
 	/**
 	 * @brief Retrieve the Display Name from the given contact ID
 	 * @param contactId Metacontact contactId
 	 */
-
 	QString getDisplayName(const QString &contactId);
 
 	/**
 	 * @brief Get the Online Status of the contact
-	 * @param displayName The displayName of the contact
+     * @param contactId Metacontact ID or displayName
 	 */
+	bool isContactOnline(const QString &contactId);
 
-	bool isContactOnline(const QString &displayName);
+	/**
+	 * Look up details for a specific contact
+	 * @param contactId Contact ID or display Name
+	 * @return A QVariantMap containing contact properties like online status, avatar, \
... +	 */
+	QVariantMap contactProperties(const QString &contactId);
 
+Q_SIGNALS:
+    /**
+     * Contact properties have changed: displayName, avatar, pending messages...
+     * @param contactId ID of the contact whose properties have changed
+     */
+    void contactChanged(QString contactId);
 
+private:
+    KopeteDBusInterfacePrivate *d;    
 };
 
 #endif
Index: kopete/kopete/org.kde.Kopete.xml
===================================================================
--- kopete/kopete/org.kde.Kopete.xml	(revision 847746)
+++ kopete/kopete/org.kde.Kopete.xml	(working copy)
@@ -72,7 +72,7 @@
       <arg name="message" type="s" direction="in"/>
     </method>
     <method name="sendMessage">
-      <arg name="displayName" type="s" direction="in"/>
+      <arg name="contactId" type="s" direction="in"/>
       <arg name="message" type="s" direction="in"/>
     </method>
     <method name="addContact">
@@ -91,17 +91,27 @@
       <arg name="displayName" type="s" direction="in"/>
     </method>
     <method name="sendFile">
-      <arg name="displayName" type="s" direction="in"/>
+      <arg name="contactId" type="s" direction="in"/>
       <arg name="fileUrl" type="s" direction="in"/>
     </method>
     <method name="getDisplayName">
-      <arg name="contactID" type="s" direction="in"/>
+      <arg name="contactId" type="s" direction="in"/>
       <arg type="s" direction="out"/>
     </method>
     <method name="isContactOnline">
-      <arg name="displayName" type="s" direction="in"/>
+      <arg name="contactId" type="s" direction="in"/>
       <arg type="b" direction="out"/>
     </method>
-
+	<method name="openChat">
+      <arg name="contactID" type="s" direction="in"/>
+    </method>
+    <method name="contactProperties">
+      <arg type="a{sv}" direction="out"/>
+      <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+      <arg name="contactId" type="s" direction="in"/>
+    </method>
+	<signal name="contactChanged">
+      <arg name="contactID" type="s"/>
+    </signal>    
   </interface>
 </node>
Index: kopete/libkopete/private/kopeteviewmanager.h
===================================================================
--- kopete/libkopete/private/kopeteviewmanager.h	(revision 847746)
+++ kopete/libkopete/private/kopeteviewmanager.h	(working copy)
@@ -59,6 +59,12 @@
     */
     KopeteView *activeView() const;
 
+    /**
+     * Returns unread messages for the given contact
+     * @param contact Message sender
+     */
+    QList<Kopete::MessageEvent*> pendingMessages( Kopete::Contact *contact );
+
 public slots:
     /**
     * Make a view visible and on top.
Index: kopete/libkopete/private/kopeteviewmanager.cpp
===================================================================
--- kopete/libkopete/private/kopeteviewmanager.cpp	(revision 847746)
+++ kopete/libkopete/private/kopeteviewmanager.cpp	(working copy)
@@ -484,6 +484,23 @@
 }
 
 
+QList<Kopete::MessageEvent*> KopeteViewManager::pendingMessages( Kopete::Contact \
*contact ) +{
+	QList<Kopete::MessageEvent*> pending;
+    foreach (Kopete::MessageEvent *event, d->eventList)
+    {
+    	const Kopete::Message &message = event->message();
+        if ( event->state() == Kopete::MessageEvent::Nothing
+        		&& message.direction() == Kopete::Message::Inbound
+        		&& message.from() == contact )
+        {
+        	pending << event;
+        }
+    }
+    
+    return pending;
+}
+
 #include "kopeteviewmanager.moc"
 
 // vim: set noet ts=4 sts=4 sw=4:



_______________________________________________
kopete-devel mailing list
kopete-devel@kde.org
https://mail.kde.org/mailman/listinfo/kopete-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic